Demo先行:https://github.com/rayshen/GIKeychainGroupDemo

该demo里有2个工程,你先运行任何一个会存储一个值,再运行另一个会访问之前的app存储的值,并修改。

官方:https://developer.apple.com/library/ios/samplecode/GenericKeychain/Introduction/Intro.html

之前博客使用过Keychain,实现了数据删除APP后还能保存,但是并没有实现APP间的共享。

实现APP间的数据共享,主要依赖于在数据存入钥匙串时,使用同一个钥匙串条目。

主要分为两部分:

1.赋予应用对某个钥匙串条目的访问权限。

2.写入时配置钥匙串条目,对kSecAttrAccessGroup的值进行设置。

一、APP对钥匙串的访问权限:

(1)未对应用APP的entitlement(授权)进行配置时,APP使用钥匙串存储时,会默认存储在自身BundleID的条目下。

(2)对APP的entitlement(授权)进行配置后,说明APP有了对某个条目的访问权限。

钥匙串的可视化效果可参见Mac的APP-钥匙串访问。

APP钥匙串访问权限的配置方法:(这里XXXXX模拟器随意,但真机必须为自己开发者账号ID,否则无法通过编译)

1.新建一个Plist文件,在Plist中的数组中添加可以访问的条目的名字(如KeychainAccessGroups.plist),结构如下:

Plist代码:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>keychain-access-groups</key>
<array>
<string>XXXXX.GrassInfoAppFamily</string>
</array>
</dict>
</plist>

2.在Build-setting中进行配置,搜索entitlement,注意路径别配置错:

二、APP对钥匙串的操作:

钥匙串的操作接口都位于Security.framework框架下,它是一个sqlite数据库,位于/private/var/Keychains/keychain-2.db,其保存的所有数据都是加密过的。

其过程可以总结为:

1.配置查询字典,格式是NSMutableDictionary,需要配置的内容下次再分析,功能就相当于写一句SQL一样。

2.进行增(SecItemAdd)、删(SecItemDelete)、改(SecItemUpdate)、查(SecItemCopyMatching)。

代码Demo里面有,这里以增为例,下面有2个语句,一个是增加到自身BundleID的钥匙串条目,一个是增加到共享的条目中。

//创建一个基本的查询字典
+ (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];
} + (void)addKeychainData:(id)data forKey:(NSString *)key{
//Get search dictionary
NSMutableDictionary *keychainQuery = [self getKeychainQuery:key];
//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);
} +(void)addShareKeyChainData:(id)data forKey:(NSString *)key{
//Get search dictionary
NSMutableDictionary *keychainQuery = [self getKeychainQuery:key];
[keychainQuery setObject:accessGroupItem forKey:(id)kSecAttrAccessGroup];
//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);
}

函数  [keychainQuery setObject:accessGroupItem forKey:(id)kSecAttrAccessGroup] 的配置,就是指定了这次写入时的钥匙串条目,不写入时默认为plist配置文件里第一个条目。

在查询中,也可以对查询的钥匙串条目进行配置,默认会对所有有权限的条目进行搜索。

三、keychain的组成:

参考博客:http://my.oschina.net/w11h22j33/blog/206713

每一个keyChain的组成如图,整体是一个字典结构.
1.kSecClass key 定义属于那一种类型的keyChain
2.不同的类型包含不同的Attributes,这些attributes定义了这个item的具体信息
3.每个item可以包含一个密码项来存储对应的密码

对于最常用密码类型,我们应该如下配置

[wrapper setObject:kSecClassGenericPassword forKey:(id)kSecClass];//class

[wrapper setObject:@"username" forKey:(id)kSecAttrAccount];//key

[wrapper setObject:@"password"forKey:(id)kSecValueData];//value

[wrapper setObject:(id)kSecAttrAccessibleAlwaysThisDeviceOnly forKey:(id)kSecAttrAccessible];

kSecAttrAccessiblein变量用来指定这个应用合适需要访问这个数据。我们需要对这个选项特别注意,并且使用最严格的选项。这个键(key)可以设置6种值。

你可以参考以下:

四、安全

前面说到,APP能够访问的keychain数据是通过其entitlements文件指定的。

但是!!如果使用带有一个*通配符的entitlments,因此它能够访问keychain中的所有条目。。或者,如果用一个包含所有访问组(access group)的entitlements文件,也能够访问所有的keychain数据。

但以上仅限模拟器,在真机调试时,假如你plist里的条目,和自己调试文件(pro file)的ID不一致时(比如:EC0880A1.company),进行真机编译的时候是会报错的。

所以真正要保证全家桶,还需要保证这些APP在同一个开发者ID下才行。

前面关于在未配置keychain-access-group的情况下,我参考别人说是默认存储在该BundleID的条目下,但实测并非存储在该条目下。具体为什么我也暂时不清楚。但是可以肯定的是,在iOS的沙盒机制中,你默认存储的条目下的K-V,其他APP是无法访问的(除了模拟器中的通配符*,真机是不行的)。

关于Keychain还有很多值得挖掘的,比如具体在sqlite数据库的表单存储方式等,有错欢迎指正。

iOS Keychain钥匙串,应用间数据共享打造iOS上的全家桶的更多相关文章

  1. iOS keyChain(钥匙串)的简单使用

    通常在开发中我们需要长久的保存某些值比如用户的账号密码等,对于隐私度很高的数据来说保证数据的安全性是尤为重要的.ios中的keyChain是一种很好的选择. 首先去开发者网站(https://deve ...

  2. iOS - keychain 详解及变化

    keychain介绍 iOS keychain 是一个相对独立的空间,保存到keychain钥匙串中的信息不会因为卸载/重装app而丢失, .相对于NSUserDefaults.plist文件保存等一 ...

  3. 聊聊iOS Keychain

    某天,小熊碰见这样一个错误 Couldn't update the Keychain Item问题处理 ,网上搜索了下网上很多解决方案,依然百撕不得骑姐.后来参考下面两篇文章.才发现是用法不正确,网上 ...

  4. iOS keyChain 的使用

    详细资料,请参看苹果官方文档Keychain Services Reference . ios中的keychain,用于保存用户的机密信息,对keychain的操作有4种,就是 增,删,改,查: Se ...

  5. iOS编程——经过UUID和KeyChain来代替Mac地址实现iOS设备的唯一标示(OC版)

    iOS编程——通过UUID和KeyChain来代替Mac地址实现iOS设备的唯一标示(OC版) 很多的应用都需要用到手机的唯一标示,而且要求这个唯一标示不能因为应用app的卸载或者改变而变化. 在iO ...

  6. (转)iOS Wow体验 - 第五章 - 利用iOS技术特性打造最佳体验

    本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第五章译文精选,其余章节将陆续放出.上一篇:Wow ...

  7. [iOS Keychain本地长期键值存储]

    目前本地存储方式大致有:Sqlite,Coredata,NSUserdefaults.但他们都是在删除APP后就会被删除,如果长期使用存储,可以使用Keychain钥匙串来实现. CHKeychain ...

  8. iOS开发技术分享(1)— iOS本地数据存储

    iOS开发技术分享(1)— iOS本地数据存储 前言: 我本是一名asp.net程序员,后来加入了iOS游戏开发队伍,到现在也有一年多的时间了.这一年来,每天都干到2.3点钟才睡觉,不为别的,只为了学 ...

  9. 李洪强iOS之集成极光推送二iOS 证书 设置指南

    李洪强iOS之集成极光推送二iOS 证书 设置指南 创建应用程序ID 登陆 iOS Dev Center 选择进入iOS Provisioning Portal. 在 iOS Provisioning ...

随机推荐

  1. SHGetFileInfo函数详解

    SHGetFileInfo函数: WINSHELLAPI DWORD WINAPI SHGetFileInfo( LPCTSTR pszPath, DWORD dwFileAttributes, SH ...

  2. spring发布和接收定制的事件(spring事件传播)

    spring发布和接收定制的事件(spring事件传播) 2012-12-26 20:05 22111人阅读 评论(2) 收藏 举报  分类: 开源技术(如Struts/spring/Hibernat ...

  3. 金山快盘+TortoiseSVN构建版本控制仓库

    金山会盘+TortoiseSVN构建版本控制仓库 之前写过一篇文章介绍 如何利用花生壳和VisualSVN Server建立远程代码仓库,具体请参照: <如何利用花生壳和VisualSVN Se ...

  4. java动态代理浅析

    最近在公司看到了mybatis与spring整合中MapperScannerConfigurer的使用,该类通过反向代理自动生成基于接口的动态代理类. 于是想起了java的动态代理,然后就有了这篇文章 ...

  5. WampServer下如何实现多域名配置(虚拟域名配置)

    之前在学习跨域的时候,我写过一篇叫做WampServer下使用多端口访问的文章,默认的 localhost 采用的是 80 端口,能使用多端口访问的核心是得新建一个端口,也就是新建一个 http 服务 ...

  6. 在Windows上将ReactNative集成到现有的Android项目

    React Natvie的官方文档的 Integrating with Existing Apps 已经很详细地教我们如何将React Natvie集成到现在的Android项目.我根据官方文档的步骤 ...

  7. Web Api 2 接口API文档美化

    使用用第三方提供的swgger ui 帮助提高 web api 接口列表的阅读性,并且可以在页面中测试服务接口. 运行程序如下: 注意:在IE中必须输入红色部分. 并且可以对方法进行测试. 在开发we ...

  8. js的几种排序

    转载:http://www.jb51.net/article/81520.htm 一.冒泡排序 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...

  9. [转]如何判断js中的数据类型

    原文地址:http://blog.sina.com.cn/s/blog_51048da70101grz6.html 如何判断js中的数据类型:typeof.instanceof. constructo ...

  10. 数组的方法 Array.map();Array.every()和Array.some();数组的indexof();检测是否是数组isArray(obj);

    数组的方法 Array.map(); 栗子: var a=[1,2,,3]; var b=a.map( function(value){return value*value} ); alert(b); ...