如何通过iOS自动填充密码保存/检索密码?

时间:2019-04-25 22:15:02

标签: ios swift nsuserdefaults keychain autofill

我正在尝试实施Apple的自动填充密码。我终于可以使用它了,但是如果确实创建了凭据,我希望我的应用程序在启动应用程序时记住用户名/密码。我目前正在使用“ KeychainSwift”窗格存储用户名和密码,但是我意识到自动填充无论如何都会创建一个新的钥匙串(它们现在显示在我的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)
    }

该请求在第二个保护声明中停止执行,因为'error'不为零。我想念什么吗?这有可能吗?

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

编辑#2 这是我理想中想要实现的目标:键盘QuickType上的自动填充选项,当用户注册/登录以将其添加到“设置”>“密码和帐户”>“网站和应用密码”。也许我无法理解自动填充的实际流程,或者iCloud钥匙串和共享Web凭据之间的区别,但是我无法全神贯注于如何实现自己的需求。

相反,发生了很多意外的事情(错误?):点击自动填充会自动创建新的凭据,但是我无法使用上面发布的代码来检索它们,但是如果我手动添加SecAddSharedWebCredential()然后可以检索它们。为什么?它们实际上都以相同的应用程序图标显示在我保存的密码中,在同一域下。此外,当关闭Signin ViewController(执行Segue)时,系统会提示我保存密码,但是当我尝试使用用户名+强烈建议的密码进行注册,然后按Back(退出ViewController)时,它仍将其添加到保存的密码,这一次甚至没有提示我保存密码!

我对所有这些大笑都感到困惑。拜托,我需要帮助:)

2 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:0)

快速解答:只有通过SecAddSharedWebCredential()手动添加密码后,您才能使用自动填充功能保存/检索密码。

这是我对整个过程的了解:

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

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

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