本地持久化用户名和密码。
KeyChain
为什么不用NSUserDefault来保存用户名和密码呢?因为NSUserDefault可以在资料沙盒中找到。
对应的沙盒路径:
1
| Library -> Preferences -> bundleId.plist
|
只要找到这个文件,储存在里面的信息便被盗取。
另外,存在KeyChain里的信息是不会随APP被删除而删除的,还可以支持iCloud同步。
api
用到的api有以下4个:
1 2 3 4
| SecItemAdd(CFDictionaryRef _Nonnull attributes, CFTypeRef _Nullable * _Nullable result) SecItemUpdate(CFDictionaryRef _Nonnull query, CFDictionaryRef _Nonnull attributesToUpdate) SecItemCopyMatching(CFDictionaryRef _Nonnull query, CFTypeRef _Nullable * _Nullable result) SecItemDelete(CFDictionaryRef _Nonnull query)
|
查询:
1 2 3 4 5 6
| NSMutableDictionary *query = [NSMutableDictionary new]; [query setValue:service forKey:(__bridge id)kSecAttrService]; //标识 [query setValue:account forKey:(__bridge id)kSecAttrAccount];//账户 [query setValue:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; //储存密码 [query setValue:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];//设置返回数据 OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
|
增加:
1 2 3 4 5 6
| NSMutableDictionary *query = [NSMutableDictionary new]; [query setValue:service forKey:(__bridge id)kSecAttrService]; //标识 [query setValue:account forKey:(__bridge id)kSecAttrAccount];//账户 [query setValue:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; //储存密码 [query setValue:pwdData forKey:(__bridge id)kSecValueData]; status = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
|
更新:
1 2 3 4 5 6 7
| NSMutableDictionary *query = [NSMutableDictionary new]; [query setValue:service forKey:(__bridge id)kSecAttrService]; //标识 [query setValue:account forKey:(__bridge id)kSecAttrAccount];//账户 [query setValue:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; //储存密码 NSMutableDictionary *newQuery = [NSMutableDictionary dictionary]; [newQuery setValue:pwdData forKey:(__bridge id)kSecValueData]; status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)newQuery);
|
删除:
1 2 3 4 5
| NSMutableDictionary *query = [NSMutableDictionary new]; [query setValue:service forKey:(__bridge id)kSecAttrService]; //标识 [query setValue:account forKey:(__bridge id)kSecAttrAccount];//账户 [query setValue:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; //储存密码 OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query);
|
demo地址:gray’s github