IOS的keychain的三种使用方法

东东 • 2016 年 09 月 11 日

一、keychain介绍

根据苹果的介绍,iOS设备中的Keychain是一个安全的存储容器,可以用来为不同应用保存敏感信息比如用户名,密码,网络密码,认证令牌。苹果自己用keychain来保存Wi-Fi网络密码,VPN凭证等等。它是一个sqlite数据库,位于/private/var/Keychains/keychain-2.db,其保存的所有数据都是加密过的。

开发者通常会希望能够利用操作系统提供的功能来保存凭证(credentials)而不是把它们(凭证)保存到NSUserDefaults,plist文件等地方。保存这些数据的原因是开发者不想用户每次都要登录,因此会把认证信息保存到设备上的某个地方并且在用户再次打开应用的时候用这些数据自动登录。Keychain的信息是存在于每个应用(app)的沙盒之外的。

这个数据是存在系统的,所以就算卸载软件,也照样存在机器中,除非恢复系统

二、keychain的使用

这里总结keychain三个使用方法,分别是苹果官方的KeychainItemWrapper

第三方封装sskeychain

通过Security.framework框架使用

这三个方法我最推崇的是使用sskeychain这个封装的方案,更加简单方便,下载和使用地址在后面,现在开始说下每一个方法的使用

三、KeychainItemWrapper的使用

KeychainItemWrapper是苹果官方推出的,链接地址:点击进入官方文档,这个因为是官方推出的,所以很多人用,但是会有点坑,使用方案,首先去官方地址或者后面我的demo中,把KeychainItemWrapper.h和KeychainItemWrapper.m引入工程,因为这个是不支持arc的,所以引入之后需要到工程的设置中,把KeychainItemWrapper.m使用-fno-objc-arc这个关闭arc//苹果官方keychain使用

-(void)AppleKeyChain

{

NSLog(@ "AppleKeyChain ");

//标识符(Identifier)在后面我们要从keychain中取数据的时候会用到。如果你想要在应用之间共享信息,那么你需要指定访问组(access group)。有同样的访问组 的应用能够访问同样的keychain信息。

KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:DAMON accessGroup:nil];

//读取

if (![wrapper objectForKey:(id)kSecValueData]) {

NSLog(@ "没有blog这个key ");

}

else{

NSLog(@ "%@ ",[wrapper objectForKey:(id)kSecValueData]);

}

// 设置service 必须

[wrapper setObject:DAMON forKey:(id)kSecAttrService];

//设置account 必须

[wrapper setObject:DAMON forKey:(id)kSecAttrAccount];

[wrapper setObject:@ "hudongdongspp " forKey:(id)kSecValueData];

//设置访问权限

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

}

使用需要注意几点[wrapper setObject: forKey:]中,key必须要是他提供的那几个,在secitem.h里面,点击kSecAttrService就可以跳转进去,不能是自定义的

keychain内部应该是根据kSecAttrService和kSecAttrAccount作为标识的,所以必须设置,否则会崩溃

如果[[KeychainItemWrapper alloc] initWithIdentifier:DAMON accessGroup:nil];里面的Identifier改变了,那么需要把kSecAttrService和kSecAttrAccount也做改变,否则会提示Couldn't add the Keychain Item.或者Couldn't update the Keychain Item.这两个错误

标识符(Identifier)在后面我们要从keychain中取数据的时候会用到。如果你想要在应用之间共享信息,那么你需要指定访问组(access group)。有同样的访问组的应用能够访问同样的keychain信息。

kSecAttrAccessiblein变量用来指定这个应用合适需要访问这个数据。我们需要对这个选项特别注意,并且使用最严格的选项。这个键(key)可以设置6种值。当然,我们应该绝对不要使用kSecAttrAccessibleAlways。一个安全点的选项是kSecAttrAccessibleWhenUnlocked。有些选项是以 ThisDeviceOnly 结尾的,如果选中了这个选项,那么数据就会被以硬件相关的密钥(key)加密,因此不能被传输到或者被其他设备看到。即使它们提供了进一步的安全性,使用它们可能不是一个好主意,除非你有一个更好的理由不允许数据在备份之间迁移。

四、sskeychain的使用方法

sskeychain是samsoffes大神封装的一个方法,不像KeychainItemWrapper需要设置太多的选项,所以很好用

使用方法就是下载之后,把SSKeychain.h和SSKeychain.m文件拖入到自己的工程中,导入头文件即可//SSKeychain使用方法

-(void)SSKeychain

{

NSLog(@ "SSKeychain ");

//读取

if (![SSKeychain passwordForService:@ "blog " account:@ "hu "]) {

NSLog(@ "没有 ");

}

else{

NSLog(@ "%@ ",[SSKeychain passwordForService:@ "blog " account:@ "hu "]);

}

//写入

[SSKeychain setPassword:@ "damon " forService:@ "blog " account:@ "hu "];

[SSKeychain setAccessibilityType:kSecAttrAccessibleAlwaysThisDeviceOnly];

}

这个操作起来比较简单明了,其实就是内部已经封装好了service等内容,不会出现KeychainItemWrapper这种没有设置就会崩溃的状况

五、Security.framework的使用

这个用到了系统库#import Security/Security.h

是用SecItemDelete((CFDictionaryRef)keychainQuery);

SecItemAdd((CFDictionaryRef)keychainQuery, NULL);

这些方法来操作keychain的

但是在网上搜索,几乎都是这个方法,所以就测试了下可以通过,所以就记录下原理+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service {

return [NSMutableDictionary dictionaryWithObjectsAndKeys:

(id)kSecClassGenericPassword,(id)kSecClass,

service, (id)kSecAttrService,

service, (id)kSecAttrAccount,

(id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible,

nil];

}

这个方法其实就是通过service这一个参数就和keychainitemwrapper里面提前预设了参数一样,把kSecAttrAccount和kSecAttrService直接用service一个参数设定了,然后把访问类型也预置了。

所以读写都会先调用这个预置的函数,就是获得同一个service里面的内容//保存

+ (void)save:(NSString *)service data:(id)data {

//Get search dictionary

NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];

//Delete old item before add new item

SecItemDelete((CFDictionaryRef)keychainQuery);

//Add new object to search dictionary(Attention:the data format)

[keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];

//Add item to keychain with the search dictionary

SecItemAdd((CFDictionaryRef)keychainQuery, NULL);

}

//读

+ (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 setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];

[keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];

CFDataRef keyData = NULL;

if (SecItemCopyMatching((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;

}

//删除

+ (void)delete:(NSString *)service {

NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];

SecItemDelete((CFDictionaryRef)keychainQuery);

}

之后使用对应的方法即可,这个函数是在demo里面的customKeyChainTool文件里面

使用方法可以这样使用//SecurityKeychain使用方法

-(void)SecurityKeychain

{

NSLog(@ "SecurityKeychain ");

NSMutableDictionary *usernamepasswordKVPairs = [NSMutableDictionary dictionary];

[usernamepasswordKVPairs setObject:@ "damon " forKey:@ "key "];

[customKeyChainTool save:@ "mmmmm " data:usernamepasswordKVPairs];

NSLog(@ "%@ ",[(NSMutableDictionary*)[customKeyChainTool load:@ "mmmmm "] objectForKey:@ "key "]);

}

六、demo下载:

七、参考文章版权属于:胡东东博客

自2017年12月26日起,『转载以及大段采集进行后续编辑』须注明本文标题和链接!否则禁止所有转载和采集行为!

☟☟如文章有用,可点击一次下方广告支持一下☟☟

安卓设置keychain_IOS的keychain的三种使用方法相关推荐

  1. 【安卓】Android播放器的三种实现方法

    转载自:http://blog.csdn.net/wozuihaole/article/details/60867076 今天来说一下Android中怎么实现视频播放,我主要说三种: 1.MediaP ...

  2. 安卓设置keychain_iOS 开发keychain 使用与多个APP之间共享keychain数据的使用

    keychain的作用: keychain,相当于MAC OS中的钥匙串,但在iOS中相对于功能非常简单.在iOS开发中如果写数据到手机沙盒中,但不管是Caches 还是NSUserDefaults ...

  3. linux设置开机自启服务,linux设置服务开机自启动的三种方式

    linux设置服务开机自启动的三种方式 这里介绍一下linux开机自动启动的几种方法,共计3种,大家可以借鉴一下!经验里面以centos 5.3系统为例! 方法1:.利用ntsysv命令进行设置,利用 ...

  4. 台式计算机蓝牙无服务,Windows10无法找到蓝牙设置三种解决方法

    说到蓝牙,大家首先想到就是手机上的,现在蓝牙用于将各种设备连接到您的计算机. 它可能是你的键盘,鼠标,手机,耳机等等.一些用户反馈说在Windows10系统中无法找到蓝牙设置,怎么办呢?针对此疑问,接 ...

  5. 设置计算机的启动顺序CDROM.C.A,bios如何设置光驱启动顺序?三种BIOS设置光驱第一启动的方法详细图解...

    在启动计算机时立即按 Delete (Del)[删除键]进入 BIOS[基本输入输出系统]设置 2 选择 Advanced BIOS Features [高级 BIOS 特性设置],并将 First ...

  6. SpringSecurity用户认证设置用户名和密码的三种方式

    文章目录 SpringSecurity用户认证设置用户名和密码的三种方式 首先明白几个单词的意思: SpringSecurity默认的用户认证 1.通过配置文件进行用户认证 2.通过配置类进行用户认证 ...

  7. Oracle的join默认为,Oracle中的三种Join方法详解

    这里将为大家介绍Oracle中的三种Join方法,Nested loop join.Sort merge join和Hash join.整理出来以便帮助大家学习. 基本概念 Nested loop j ...

  8. oracle hash join outer,CSS_浅谈Oracle中的三种Join方法,基本概念 Nested loop join: Outer - phpStudy...

    浅谈Oracle中的三种Join方法 基本概念 Nested loop join: Outer table中的每一行与inner table中的相应记录join,类似一个嵌套的循环. Sort mer ...

  9. lopa分析_【风险分析方法】HAZOP、LOPA和FMEA三种分析方法,如何做到信息共享?...

    导 读 信息是人们对事物的了解的不确定性的减少或消除,其功能是表征物质客体成分,结构,状态,特性等属性.信息共享的目的在于减少或消除信息源所需的不确定性.石油化工行业由于设备多,生产过程复杂,危险元素 ...

最新文章

  1. mysql 5.7 修改root 密码
  2. 360 您访问的是存在未经证实信息的网站
  3. EventBank闪耀企业服务 荣获“2017中国企业服务云年度产品”奖
  4. 错误: 找不到或无法加载主类 Test4解决方案
  5. Linux fork()函数底层CopyOnWrite写时复制实现原理剖析
  6. 关于凸优化的一些简单概念
  7. VTK:Math之NormalizeVector
  8. Btree索引和Hash索引
  9. Effective Java 在工作中的应用总结
  10. 使用RunWith注解改变JUnit的默认执行类,并实现自已的Listener
  11. Net学习日记_ADO.Net_2_练习(treeView)
  12. LaTex中“图片引用失败,显示(??)”的解决办法
  13. 华为/华三:OSPF多区域配置
  14. centos 5开机出现PCI错误:Not using MMCONFIG
  15. 题目:学习成绩 = 90分的同学用A表示,60 - 89分之间的用B表示,60分以下的用C表示
  16. Unity3D 内存释放 垃圾回收
  17. python读取文件时的相对路径
  18. 芯片数据分析步骤1 芯片数据下载-GEO
  19. 【ipone开发学习】-2、利用现有资源第二步 硬盘安装Snow LeopardXcode
  20. 读书笔记:《心若菩提》 曹德旺

热门文章

  1. ECSHOP goods表字段分析
  2. 【实战Docker】SVN服务
  3. 微信开发者工具网络连接失败问题解决方法
  4. codeforces 514B
  5. 【python】根据文件(图片)名字,删除符合条件的文件(图片)
  6. linux常用的引导管理器,多重引导管理器Grub使用详解
  7. matlab曲线已知y求x,已知X、Y用MATLAB绘制曲线
  8. java重绘橡皮筋_【译】谈橡皮筋特效的解决方案
  9. 计算机专业常用英语(转)
  10. 魔兽世界如何攻打纳克萨玛斯电男?