用户名密码不能保存在NSUserDefault里面,这个应该是共识。一般是把重要的东西存在keychain里面,keychain是可以被破解的,最好不要明文存储。
keychain里的东西是存在于每个app的沙盒之外的,所以keychain里保存的信息不回因app卸载而丢失。
使用Keychain需要引入Security.framework
框架
苹果官方有个GenericKeychain示例代码,不过它不是ARC的,用的时候在Building Phases
-> Compile Sources
里面找到KeychainItemWrapper.m
,给它添加上标志-fno-objc-arc
。
假如说你只是要保存个用户名密码,那么使用KeychainItemWrapper就够了,具体的用法如下:
1.首先创建一个KeychainItemWrapper
对象
KeychainItemWrapper * wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"myKeychainIdentifier" accessGroup:nil];
其中设置accessGroup为nil,表示不在应用之间共享。
2.假如说你要保存用户名和密码,那么就可以调用
[wrapper setObject:username forKey:(id)kSecAttrAccount];
[wrapper setObject:password forKey:(id)kSecValueData];
3.如果要从keychain里面取出保存的用户名或者密码,可以这样
NSString * username = [wrapper objectForKey:(id)kSecAttrAccount];
NSString * password = [wrapper objectForKey:(id)kSecValueData];
可以判断username或者password是不是nil或者@“”,来判定是否从来没存过keychain。
keychain实际是一个数据库,里面保存的所有东西都是加过密的。苹果自己用keychain来保存wifi密码、VPN凭证等。在iOS里面,如果要在app之间共享keychain就要是同一个公司的证书。对于每个app来说,keychain都有两个访问区,私有访问区和公共访问区。私有访问区只对本应用可见,公共访问区可以对多个应用可见,即使用keychain access group
声明。
keychain钥匙串中的条目称为SecItem,它是存储在CFDictionary中的。SecItem有五类:通用密码、互联网密码、证书、密钥、身份。大多数情况下使用keychain的时候都是保存通用密码。在钥匙串中搜索某个SecItem的时候,可以根据自己的标识符来搜索。通用密码条目都包含属性kSecAttrGeneric
,可以用它来存储标识符。
kSecClass定义属于哪一种类型的keychain,不同的类型有不同的attributes,这些attributes定义了这个item的具体信息,每个item可以包含一个密码项来存储对应密码。
钥匙串中的条目都有可搜索的attribute和加过密的value。对于通用密码条目,比较重要的属性有账户kSecAttrAccount、服务kSecAttrService、标识符kSecAttrGeneric.
官方文档里面通用密码条目所有的属性如下: