iOS钥匙串中受密码保护的条目
您将拥有应用程序的名称,而不是“ keychain-sample”。
请注意,在这种情况下, SecItemCopyMatching
调用是同步的,必须在后台线程上完成以防止主线程阻塞。
如果用户输入了错误的密码,那么iOS会自动重新显示提示。 在用户输入正确的密码或点击“取消”或超过允许的最大尝试次数(由系统定义的情况下,如果我没有记错的话,为5次), SecItemCopyMatching
调用将不会返回。
使用LAContext.evaluateAccessControl
如果我们要手动控制尝试次数,并且还避免长时间运行阻塞调用SecItemCopyMatching
则可以使用稍微不同的方法:
在这里,我们创建一个LAContext
实例,并为它调用带有operation: .useItem
evaluateAccessControl
operation: .useItem
。 这个evaluateAccessControl
调用将触发与我们之前相同的UI提示。 但是,后续的SecItemCopyMatching
调用不会被阻止。
同样值得注意的是,由于这个原因, localizedReason
参数在此evaluateAccessControl
调用中被忽略,并且UI提示与前面的情况完全相同。
为SecItemCopyMatching
准备数据的关键点是将LAContext
实例设置为kSecUseAuthenticationContext
密钥的值,并且还为kSecUseAuthenticationUI
设置kSecUseAuthenticationUIFail
值。
在这种情况下,第一次尝试输入错误密码后,我们的loadPassProtected
调用将失败,如果要允许第二次尝试,我们将必须手动重复该过程。 这样我们就可以控制尝试次数。
顺便说一句,如果我们在SecItemCopyMatching
调用中不使用kSecUseAuthenticationUIFail
,则系统将以与以前相同的方式自动处理错误的密码。 并且SecItemCopyMatching
将变得阻塞。
自定义用户界面,而不是系统提示
现在,如果系统密码提示不适用于我们的应用程序设计怎么办? 看来我们可以实现自己的用户界面来输入密码,只需将密码值提供给钥匙串API。
为此,我们必须创建一个LAContext
实例,并将从用户获得的密码设置LAContext
实例。 与将条目保存在钥匙串中时的方式相同:
在这里,我们还使用了非阻塞的SecItemCopyMatching
调用。
还应注意,您需要一个真实的设备来测试此代码。 它在模拟器中不起作用。 我看到有人提到它在关闭密码的真实设备上不起作用,例如:
iOS钥匙串– LAContext.setCredential(data,.applicationPassword)在模拟器上返回false
似乎applicationPassword与设备的系统密码结合使用。 因此,… stackoverflow.com
但是我的测试表明,至少在iOS 12中,当我关闭设备上的密码时,它可以正常工作。
如本文中所述,用于创建和读取受密码保护的条目的示例代码可以在github上的该项目中找到:
algrid /钥匙串样本
iOS钥匙串用法示例。 通过在GitHub上创建一个帐户来为algrid / keychain-sample开发做出贡献。 github.com
我希望这些信息对提高您的iOS应用程序的安全性很有帮助。 如果您发现问题或有任何建议,请告诉我。