如何从iOS自动填充密码中保存/检索密码?



我正在尝试实现Apple的自动填充密码。我终于让它工作了,但如果确实创建了凭据,我希望我的应用程序在应用程序启动时记住用户名/密码。我目前使用"钥匙串Swift"pod存储用户名和密码,但我意识到自动填充无论如何都会创建一个新的钥匙串(它们现在出现在我的iPhone保存的密码中),所以我不妨直接使用这些凭据。 我尝试用这个检索它,但说"找不到匹配的项目":

SecRequestSharedWebCredential(nil, nil){ credentials, error in
guard let credentials = credentials else { print("Keychain: No credentials found"); return }
guard error == nil else { print("Keychain Error:", error?.localizedDescription ?? "no error description"); return }
let credential: CFDictionary = unsafeBitCast(CFArrayGetValueAtIndex(credentials, i), to: CFDictionary.self)
let server = unsafeBitCast(CFDictionaryGetValue(credential, unsafeBitCast(kSecAttrServer, to: UnsafeRawPointer<Void>.self)), to: CFString.self)
let account = unsafeBitCast(CFDictionaryGetValue(credential, unsafeBitCast(kSecAttrAccount, to: UnsafeRawPointer<Void>.self)), to: CFString.self)
let password = unsafeBitCast(CFDictionaryGetValue(credential, unsafeBitCast(kSecSharedPassword, to: UnsafeRawPointer<Void>.self)), to: CFString.self)
print("Keychain OK:", server, account, password)
}

请求在第二个保护语句处停止执行,因为"错误"不是 nil。我错过了什么吗?这可能吗?

编辑#1: 我一直在阅读所有这些内容,并且感觉每当用户注册或登录时,我都必须单独保存/加载用户名/密码组合(通过钥匙串或UserDefaults)。任何人都可以确认这是预期的行为吗?对我来说似乎很奇怪,因为自动填充已经将这些凭据存储在某个地方(我假设是钥匙串),因为 FaceID 会弹出并使用我在注册期间提供的正确用户名/密码自动填充文本字段。

编辑#2这就是我理想地想要实现的目标:键盘QuickType上的自动填充选项,以及当用户注册/登录时将其添加到">密码和帐户>网站和应用密码"中显示的保存密码中"。也许我不了解自动填充的实际流程,或者iCloud钥匙串和共享网络凭据之间的区别,但我无法弄清楚如何实现我需要的东西。

相反,发生了许多意想不到的事情(错误?):点击自动填充会自动创建新凭据,但我无法使用上面发布的代码检索它们,但是如果我使用SecAddSharedWebCredential()手动添加它,我就可以检索它们。为什么?从字面上看,它们都出现在我保存的密码中,在同一域下,具有相同的应用程序图标。此外,当登录视图控制器被关闭(执行 Segue)时,我会被提示保存密码,但是当我尝试使用用户名 + 强烈建议的密码注册然后按"返回"(这会关闭 ViewController)时,它仍然将其添加到保存的密码中,这次甚至没有提示我保存密码!

我对这一切感到困惑,哈哈。拜托,我需要帮助:)

快速回答:仅当您使用SecAddSharedWebCredential()手动添加密码时,才能使用自动填充功能保存/检索密码。

以下是我对整个过程的了解:

只需启用自动填充(将contentType设置为.username.password/.newPassword,以及添加关联域),当我登录或使用自己的密码注册时,当活动ViewController被关闭时,应用程序会自动提示"保存密码?"(有点酷,我不需要添加任何代码即可将这些凭据添加到iCloud钥匙串)。但是,如果我使用Apple的"强密码"注册,则当我的活动ViewController被关闭时(即通过点击"后退"按钮,使用interactivePopGestureRecognizer,甚至成功完成注册),它会自动将凭据添加到iCloud钥匙串,甚至不显示"保存密码?"提示(没有用户知情或同意)。我觉得这不应该发生,所以我刚刚提交了一个错误。

现在,当自动添加凭据时,我们无法检索具有预期功能的密码SecRequestSharedWebCredential(nil,nil):不会找到凭据。我们只有在使用SecAddSharedWebCredential()手动添加密码时才能检索密码(我也发现这有点像奇怪的行为,因为最终结果完全相同)。但这不是我想要的,因为SecAddSharedWebCredential()的提示不同且太啰嗦,即使我想静默检索它,SecRequestSharedWebCredential()也会显示提示(例如,通过将用户名存储在 UserDefaults 中并使用SecRequestSharedWebCredential(nil, username)检索它。

结论:我无法做我想做的事(使用 iCloud 钥匙串保存并静默检索正确的凭据,而无需在我自己的应用程序钥匙串中复制副本)。我最终将用户名/哈希单独存储在我的应用程序钥匙串上以进行自动登录,并且我启用了自动填充功能以进行快速登录,以防用户需要临时注销(这会从我的应用程序钥匙串中删除用户名/哈希)同时将密码保存在 iCloud 钥匙串中。

您不应存储用户名和密码。首次登录用户时,应生成令牌。令牌应存储在您的应用程序钥匙串中。当用户第二次启动应用时,应使用该令牌登录。

存储令牌比存储用户名和密码安全得多。

如果要存储密码,则至少仅存储密码哈希而不是纯文本。

最新更新