使用 Keychain 存储登录态需要注意的一个坑

我们通常会在 Keychain(钥匙串)中存储一些密码、用户登录态等敏感数据,一是可以提高保存数据的安全性;二是当用户卸载 App 后重新安装,可以自动登录保留上次的登录态;三是同一开发者账号下的不同 App,如果是采用同一套账户体系,就可以通过 Keychain Groups 共享登录态。

我们的 App 之前都是只把用户的登录态保存在 Keychain 中,并在 App 启动时去读取它,这一直也都没什么问题。前一段时间我们的 App 由于业务合规的原因审核被拒,按照苹果的要求不得不把 App 从公司的 A 开发者账号转让到 B 开发者账号下(公司旗下有很多不同主体的开发者账号),转让过程很顺利,但发版后短时间内收到大面积的用户反馈说,更新新版本后提示“登录失效,需要重新登录”。

原因很容易就可以猜到,App 从 A 转让到 B,就无法读取保存在 A 账号下的 Keychain 数据了,用户更新版本覆盖安装后,打开 App 也就无法获取之前的登录态了。

而且对于这种已经发生的问题,我们似乎也没有什么有效的补救措施,临时加急再发一版似乎也解决不了问题,因为之前的 Keychain 数据就是读取不到了,总不能再把 App 转让回去吧,😂

那么如何未雨绸缪预防以后再发生这种因为转让 App 导致存储在 Keychain 中的登录态丢失读取不到呢?(虽然出现转让 App 的概率非常低)

我们在新版本中采用了一种兼容的方法:把用户的登录态同时加密存储在本地缓存(Sandbox)和 Keychain 中,在 App 启动时,优先从 Keychain 中读取,如果 Keychain 中取不到,就从本地缓存中取(然后再把本地缓存的同步到 Keychain 中,因为即使 App 转让了,用户更新版本覆盖安装后 Sandbox 中的数据是不会变的),如果两处都取不到,就认为未登录。

你有没有更好的解决方案?欢迎留言讨论。

另外,有很多人通过 Keychain 来存储设备唯一标示符,也需要注意这个问题。

关于 Keychain 如何使用,可以参考苹果官方文档:GenericKeychain,而关于 Keychain 滥用问题的讨论,可以看 V2EX 的这个帖子