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. XmlSpy / XSD 以及 验证

    很早以前看过一句话:“XML就象空气”,在企业应用开发中XML是一个重要的数据交换标准.而XSD则可以用来校验XML的数据格式是否正确. 一个典型的XSD文件如下: <?xml version= ...

  2. favicon.ico文件简介

    本地调试时,控制台经常会打印如下的错误(对 favicon.ico 的请求在 chrome 调试面板下不可见,可在抓包工具,比如 Fiddler 中看到): favicon.ico 是啥?看下面这张图 ...

  3. <实训|第十三天>linux中ACL权限控制以及磁盘配额,附编译属于自己的linux内核

    [root@localhost~]#序言 首先讲讲昨天关于缩容失败,开不机的解决方法:ACL权限也算是一个很重要的知识点,不难,但是很实用:磁盘配额一般不需要自己弄,但是要懂得原理.剩下的就是编译属于 ...

  4. C#版的MapReduce

    如果不知道MapReduce是怎么工作的,请看这里,如果不知道MapReduce是什么,请google之! 今天“闲”来无事,忽想起C#里没有MapReduce的方法,构思之,coding之: #re ...

  5. Euler Level 2

    闲下来的时候就做点,慢慢的也终于到达Level 2了.

  6. json数据转换失败json_last_error int(4)

    最近在程序中使用json_decode($data,true);转换失败, 并且使用 json_last_error();方法返回最后一次转换的错误,json_last_error();返回int(4 ...

  7. Android快速开发框架LoonAndroid (转)

    1.源码简介: 主要有以下模块: (1) 自动注入框架(只需要继承框架内的application既可) (2) 图片加载框架(多重缓存,自动回收,最大限度保证内存的安全性) (3) 网络请求模块(继承 ...

  8. Chrome DevTools good good study day day up

    Chrome DevTools 官方页面 https://developer.chrome.com/devtools

  9. poj2186 强连通缩点

    Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 29773   Accepted: 12080 De ...

  10. 新版汉诺塔(UVa10795 - A Different Task)

    题目介绍: 标准的汉诺塔上有n个大小各异的盘子.现给定一个初始局面(见图1),求它到目标局面(见图2)至少需要移动多少步? 移动规则:一次只能移动一个盘子:且在移动盘子之前,必须把压在上面的其他盘子先 ...