現在正在接觸蘋果IOS開發的項目,使用到如何通過KeyChain實現相同簽名下發布的應用之間的數據共享功能。現分享下心得。
項目是在XCODE6.2開發環境進行的。
IOS中訪問KeyChain有兩種方法,且這兩種方法不能混用,不然會出現無法共享的問題。不過獲取的方法可以通用,以下先給出Keychain訪問的函數原型。
KeyChain.h
[objc] view plaincopyprint?
- + (void)save:(NSString *)service dataid)data;
- + (id)load:(NSString *)service;
- + (void)deleteNSString *)service;
KeyChain.m
[objc] view plaincopyprint?
- //私有方法,搜索KeyChain數據集。
[objc] view plaincopyprint?
- + (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
- return [NSMutableDictionary dictionaryWithObjectsAndKeys:
- (__bridge id)kSecClassGenericPassword,(__bridge id)kSecClass,
- service, (__bridge id)kSecAttrService,
- service, (__bridge id)kSecAttrAccount,
- (__bridge id)kSecAttrAccessibleAfterFirstUnlock,(__bridge id)kSecAttrAccessible,
- nil nil];
- }
[objc] view plaincopyprint?
- // 保存KeyChain數據,data裡傳遞的<span >NSMutableDictionary類型的對象,對象裡的 KEY為你需要共享數據的子KEY。</span>
- + (void)save:(NSString *)service dataid)data {
- //Get search dictionary
- NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
- //Delete old item before add new item
- SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
- //Add new object to search dictionary(Attention:the data format)
- [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(__bridge id)kSecValueData];
- //Add item to keychain with the search dictionary
- SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL);
- }
[objc] view plaincopyprint?
- //加載KeyChain數據,返回的是一個NSMutableDictionary類型的對象,通過NSMutableDictionary中objectForKey的方法,傳遞子KEY來獲取對應共享的數據。
- + (id)load:(NSString *)service {
- id ret = nil;
- NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
- //Configure the search setting
- //Since in our simple case we are expecting only a single attribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue
- [keychainQuery setObjectid)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
- [keychainQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
- CFDataRef keyData = NULL;
- if (SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
- @try {
- ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
- } @catch (NSException *e) {
- NSLog(@"Unarchive of %@ failed: %@", service, e);
- } @finally {
- }
- }
- if (keyData)
- CFRelease(keyData);
- return ret;
- }
[objc] view plaincopyprint?
- //刪除KeyChain數據,這裡的service傳入的是主Key,所以刪除的是所有的數據。
- + (void)deleteNSString *)service {
- NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
- SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
- }
下面來說如果配置KeyChain。第一種方法:通過plist方式進行
1、創建一個新文件,選擇Property list文件。
2、創建一個新的子節點,取名為keychain-access-groups
3、修改節點keychain-access-groups的類型為Array
4、在keychain-access-groups節點下添加子節點,填入你的主KEY名稱
第二種方式:直接通過XCODE特性來配置(非常簡單)
1、選擇工程配置中的capabilities頁面
2、打開KeyChain Sharing開關,設置你的主KEY的名稱。
注:以上兩種不能混用,應用會優先使用第一種方法來處理KeyChain共享。