向当前捆绑包 ID 添加前缀会重置钥匙串吗?

Posted

技术标签:

【中文标题】向当前捆绑包 ID 添加前缀会重置钥匙串吗?【英文标题】:adding prefix to your current bundle id resets the keychain? 【发布时间】:2015-08-24 13:10:25 【问题描述】:

我有一个 app(app1) 在 appstore 中,捆绑包 ID 为 com.x。y 现在我正在同一个开发者帐户下开发另一个应用程序(app2),捆绑包 id 为 com.x。z

我想让存储在 app1 中的钥匙串值对 app2 可用。

keychain 的可用性由 keychain-access-groups 决定。 因此,如果我将前缀(当前团队 ID)添加到两个捆绑包 ID,我就可以获取这些值。示例 teamid.com.x.y teamid.com.x.z

问题是当我将前缀添加到 appstore 中的 app1 时,它会再次要求我不想要登录凭据,因为应用程序有很多用户。 我之前没有使用前缀,我只是添加了它们。 有没有一种方法可以让我在无需用户再次登录的情况下获得这两个应用程序的钥匙串访问权限。

【问题讨论】:

【参考方案1】:

首先,重要的是要意识到 Xcode 已经将 AppIdentifierPrefix 添加到您的标识符中。不幸的是,它在 GUI 中隐藏了它,但如果你打开权利 plist,你会看到它。这是用于签署应用程序的标识符,它是用于强制访问控制的部分。我不相信您添加的 teamid 前缀真的有任何作用。我通常会推荐一个访问组com.x.sharedcom.x.appgroup.shared,而不是使用com.x.z(我假设com.x.y 已经存在,所以你不能改变它)。

我在这里假设您不想强迫用户升级 App1,对吗?我正在根据这个假设继续前进。

如果您可以升级 App1(不需要升级,但要确​​保所有 客户都有升级版本),则仅存储在 com.x.y 中(如果存在)。否则,存储在com.x.shared

从钥匙串中读取时,不要使用访问组。这将获得第一个匹配的记录。 当您写入钥匙串时,请使用您读取的记录中的访问组。

如果您现在根本不想升级 App1(是否需要),那么只需始终在 App2 中读取和写入 com.x.y

当您准备好终止 com.x.y 组时(如果您最终能够升级所有支持 App1 的用户),那么您可以切换到:

com.x.y 读取。如果找到,请将其删除,然后将其重新创建为 com.x.shared。您可以在应用程序启动时一次性执行此操作(只需写一个 NSUserDefaults 说明您已经完成了。 从那时起,始终明确使用com.x.shared

这里的关键工具是,当您请求显式访问组时,您必须提供全部内容,包括您的 AppId(未显示在 Xcode GUI 中)。您当然可以对其进行硬编码,但更好的解决方案是动态查询它。我使用David H's code的更新版本:

- (NSString *)bundleSeedID 
  NSDictionary *query = @ (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
                           (__bridge id)kSecAttrAccount : @"bundleSeedIDQuery",
                           (__bridge id)kSecAttrService : @"",
                           (__bridge id)kSecReturnAttributes : (id)kCFBooleanTrue
                           ;
  CFDictionaryRef result = nil;
  OSStatus status = SecItemCopyMatching((__bridge CFTypeRef)query,
                                        (CFTypeRef *)&result);
  if (status == errSecItemNotFound)
    status = SecItemAdd((__bridge CFTypeRef)query, (CFTypeRef *)&result);
  if (status != errSecSuccess)
    return nil;
  NSString *accessGroup = [(__bridge NSDictionary *)result
                           objectForKey:(__bridge id)kSecAttrAccessGroup];
  NSArray *components = [accessGroup componentsSeparatedByString:@"."];
  NSString *bundleSeedID = components[0];
  CFRelease(result);
  return bundleSeedID;

这将在运行时告诉您您的前缀。它这样做是通过创建一个伪造的钥匙串条目,然后查询它并查看附加到它的访问组。

您可能对Renaissance.io 2014 中Getting Security and Privacy Right 的第一部分感兴趣。您可以跳至“使用钥匙串保护机密”。

【讨论】:

非常感谢 Rob。真的很感谢你的时间。这确实很有意义。 M 在上面暗示并将投票给您,并让您知道是否遇到问题。 这确实很有帮助。所以在 app2 中,我创建了访问组 com.x.y,并且我能够读取钥匙串。在将 app2(new) 推送到 appstore 之前,我将推送 app1 更新。所以我应该在 app1 更新中将 app1 钥匙串迁移到 com.x.shared。并将 app2 与访问组 com.x.shared 一起使用?? @Abhijeet_dce 是的,但请记住,人们可能会在升级 app1 之前安装 app2,因此您可能仍需要同时在 app2 中读取和写入旧密钥。

以上是关于向当前捆绑包 ID 添加前缀会重置钥匙串吗?的主要内容,如果未能解决你的问题,请参考以下文章

用户可以清除钥匙串吗?

如何在模拟器中重置钥匙串?

PhoneGap 构建 iOS 钥匙串访问?

重置设备上的钥匙串

启用钥匙串共享会改变您的 AppID 吗?

使用 Swift 向 iOS 钥匙串添加项目和查询