如何实现自动填充凭据提供程序扩展 - iOS 11,Swift4

4
我已经在iOS Autofill凭证扩展方面工作了很长时间。我查看了很多iOS文章和视频,但是我无法在快速输入栏中显示凭据,重置事项已成功集成。有人能给我快速帮助吗?
使用苹果分享的以下视频和网址: https://developer.apple.com/videos/play/wwdc2018/721 https://developer.apple.com/documentation/authenticationservices
我正在使用下面的代码将凭据保存到特定域的钥匙串中。
    let keychain = Keychain(server: "instagram.com", protocolType: .https, authenticationType: .htmlForm)
    keychain["emailAddress"] = "Password"

使用以下代码保存域名:

func savedomain(domain: String, account: String, password: String, completion: ((Bool, SharedWebCredentialsManagerError?) -> Void)? = nil) {
    SecAddSharedWebCredential(domain as CFString, account as CFString, password as CFString?) { error in
        guard let error = error else {
            completion?(true, nil)
            return
        }
        let errorDescription = CFErrorCopyDescription(error) as String
        let saveFailedError = SharedWebCredentialsManagerError.saveFailed(errorDescription)
        completion?(false, saveFailedError)
    }
}

我创建了一个自动填充扩展并获取了保存的凭据,但无法在Safari的快速输入栏中显示Instagram.com的凭据。


你有解决方案吗? - Vaisakh KP
3个回答

2
我已经为所有社交网站实现了自动填充扩展程序,分享我的源代码以保存与域名相关的电子邮件ID和密码。
class func save(key: String, data: Data) -> OSStatus {
    let query = [
        kSecClass as String       : kSecClassGenericPassword as String,
        kSecAttrAccount as String : key,
        kSecValueData as String   : data ] as [String : Any]

    SecItemDelete(query as CFDictionary)

    return SecItemAdd(query as CFDictionary, nil)
}

我已经在我的自定义KeyChainManager类中编写了上面的“保存”功能。同时,我在KeyChainManager类中添加了以下代码,如下所示。
extension Data {

init<T>(from value: T) {
    var value = value
    self.init(buffer: UnsafeBufferPointer(start: &value, count: 1))
}

func to<T>(type: T.Type) -> T {
    return self.withUnsafeBytes { $0.load(as: T.self) }
}

我通过调用我们的KeyChainManager类来保存VC中的数据,代码如下所示:

}

let email = (txtEmail?.text ?? "").trimmingCharacters(in: .whitespacesAndNewlines)
        let password = (txtPassword?.text ?? "").trimmingCharacters(in: .whitespacesAndNewlines)
        let domain = (txtDomain?.text ?? "").lowercased().trimmingCharacters(in: .whitespacesAndNewlines)
        
        let user = User(email: email, password: password, key: self.key, domain: domain, identifier: self.keyIdentifier)
        let data = (try? JSONEncoder().encode(user)) ?? Data()
        let _ = KeyChain.save(key: "\(self.keyIdentifier)", data: data)

这些都是用来保存我们的凭证的内容,现在主要问题是如何在我们的扩展程序CredentialProviderViewController.swift中列出所有已保存的凭证。
为此,我在KeyChainManager类中添加了以下方法:
class func load(key: String) -> Data? {
    
    let query = [
        kSecClass as String       : kSecClassGenericPassword,
        kSecAttrAccount as String : key,
        kSecReturnData as String  : kCFBooleanTrue!,
        kSecMatchLimit as String  : kSecMatchLimitOne ] as [String : Any]

    var dataTypeRef: AnyObject? = nil

    let status: OSStatus = SecItemCopyMatching(query as CFDictionary, &dataTypeRef)

    if status == noErr {
        return dataTypeRef as! Data?
    } else {
        return nil
    }
}

在扩展的CredentialProviderViewController.swift中调用此函数:

users.removeAll()
    for i in 0..<1000000 {
        if let encodedData = KeyChain.load(key: "\(i)")  {
            let user = try! JSONDecoder().decode(User.self, from: encodedData)
            if user.key == key && ((serviceIdentifier.contains(user.domain ?? "")) ) {
                users.append(user)
            }
        }else{
            break
        }
    }

我希望这篇内容能对您有所帮助,因为我花了很多天的时间才创建出一个演示 :) :) 如果它对您有用,请在下面留言 :) :)

谢谢, Anjali。


0

我如何实现 ASCredentialIdentityStore 的人口统计:

        var firstItem = ASPasswordCredentialIdentity(serviceIdentifier: ASCredentialServiceIdentifier(identifier: "https://online.somebank.com/auth/login", type: .URL), user: "login@bank.com", recordIdentifier: nil)
    ASCredentialIdentityStore.shared.replaceCredentialIdentities(with: [firstItem]) { result, error in
        if result {
            print("saved")
        }
    }

在我的情况下一切都工作得很完美。 因此我从远程获取所有密码,然后将可用的密码填充到 ASCredentialIdentityStore 中。

0
你需要填充 ASCredentialIdentityStore 才能让 QuickType 栏正常工作。请查看 ASCredentialProviderViewController 的描述:

可选地向共享的 ASCredentialIdentityStore 添加 ASPasswordCredentialIdentity 实例,以便在 QuickType 栏中直接使用身份。

这也在您所参考的 WWDC 演示中有所描述。


有没有想法如何填充 ASCredentialIdentityStore?我尝试了以下代码:let store = ASCredentialIdentityStore.shared let passwordIdentity = ASPasswordCredentialIdentity(serviceIdentifier: ASCredentialServiceIdentifier(identifier: "chase.com", type: .URL), user: "jbrantl8", recordIdentifier: nil) store.saveCredentialIdentities(identities) { (success, error) in - metamonkey
错误:源文件中的编辑器占位符和错误:无法将类型为“ASPasswordCredentialIdentity”的值转换为预期的参数类型“[ASPasswordCredentialIdentity]”。 - metamonkey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接