//研究了一天 发现网络上大部分关于keychain的讲解都不详细......自己更是踩雷踩了一天才把KeyChain使用与共享数据研究成功 分享到这里 希望大家不用再劳累这么一次
Apple文档上说iOS的keyChain是一个相对独立的空间,当程序替换,删除时并不会删除keyChain的内容,这个要比Library/Cache好。刷机,恢复出厂应该就没有了。自己的程序只能访问自己的keychain,同意开发者下的程序通过设置group可以互相共享同组的keychain(即同一开发者帐号下面的App可以通过这种方式共享数据,不同开发者帐号的App--大叔也无能为力,苹果还是不允许访问(当然传值的话,可以通过[[UIApplication sharedApplication] openURL:url]来实现)),从而实现程序间可以共同访问一些数据。
//keyChain 中一些参数的解释
1.设置Class值,每个Class对应的都有不同的参数类型
2.用户确定的参数,一般是程序中使用的类别,比如说是"Password"或"Account Info",作为search的主力条件
3.设置Group,如果不同程序都拥有这个组,那么不同程序间可以共享这个组的数据
4.只返回第一个匹配数据,查询方法使用,还有值kSecMatchLimitAll
5.返回数据为CFDicitionaryRef,查询方法使用
6.执行查询方法,判断返回值
eg:这个是none-ARC的代码哦!ARC情况下会有bridge提示。
首先我们创建一个Plist文件 名字随便定义 我这里是KeychainAccessGroups.plist
//需要特别注意的是 keyChain共享数据 只能在正式环境中使用,测试环境与企业帐号都不能使用accessGroup达到共享数据目的
所以为了方便平时调试 Target--->Build Settings--->Code Signing Entitlements中 我们只在Release中加入 O2O手边/KeychainAccessGroups.plist(这是你配置的KeychainPlist文件所在路径)
1.如果你在 addkey时,没有指定group,则会默认添加你keychain-access-groups里第一个group,如果你没有设置Entitlements,则默认使用对应的程序的bundle name,比如com.jv.key1,表示只能给自己程序使用。
2.如果你程序添加的group并不存在你的配置文件中,程序会奔溃,表示无法添加。因此你只能添加你配置文件中支持的keychain。
3. keychain-access-groups 中的 accessGroup 可以直接用 $(AppIdentifierPrefix)* 表示AppID.* (类似于Bundle ID *表示任意字符)如果你的AppID是GGB3GZ5GNJ 则上面为GGB3GZ5GNJ.*表示该开发者帐号下面的所有App都共享数据
4. accessGroup格式为“yourAppID.com.yourCompany.whatever”就是你要起的公共区名称,除了whatever字段可以随便定之外,其他的都必须如实填写。这个文件的路径要配置在 Project->build setting->Code Signing Entitlements里,否则公共区无效,配置好后,须用你正式的证书签名编译才可通过,否则xcode会弹框告诉你code signing有问题。所以,苹果限制了你只能同公司的产品共享KeyChain数据,别的公司访问不了你公司产品的KeyChain。
下面是代码实现
代码实现 首先请下载Apple官方Demo 取出KeychainItemWrapper.h KeychainItemWrapper.m 文件 (注意由于这个Demo是04年就有了 用的是MRC 所以ARC环境下添加-fno-objc-arc)
+(NSString *)getIdentifierForVendor{
KeychainItemWrapper *keyChainItem=[[KeychainItemWrapper alloc] initWithIdentifier:@"O2OUserAppHankUUID" accessGroup:@"GGB3GZ5GNJ.*"];
NSString *strUUID = [keyChainItem objectForKey:(__bridge id)kSecAttrAccount];
return strUUID;
}
//存储字符串到KeyChain
+(void)saveUUID:(NSString *)uid{
KeychainItemWrapper *keyChainItem=[[KeychainItemWrapper alloc] initWithIdentifier:@"O2OUserAppHankUUID" accessGroup:@"GGB3GZ5GNJ.*"];
[keyChainItem setObject:uid forKey:(__bridge id)kSecAttrAccount];<span style="color:#3333ff;">注意方法“- (void)setObject:(id)inObject forKey:(id)key;”里参数“forKey”的值应该是Security.framework 里头文件“SecItem.h”里定义好的key,用其他字符串做key程序会崩溃!</span>
}
注意
accessGroup 是为了同一个开发者下不同App数据共享 如果只是为了使用KeyChain存储数据 则这个参数可以传nil;
(如果你没有设置Entitlements,则默认使用对应的程序的bundle name ,也就是nil表示只有该App才能访问该数据,这个上面已经说过 )
GGB3GZ5GNJ.* 中的GGB3GZ5GNJ 是App ID Prefix ---(注意不是Apple ID)
GGB3GZ5GNJ.* 表示 以GGB3GZ5GNJ开头的所有App都能共享该数据 如果想限制特定App 则为GGB3GZ5GNJ.com.yourCompany.whatever
好了 现在自己创建工程去试一下吧