使用KeyChain處理用戶名和密碼
KeyChain
本地持久化用戶名和密碼是常見的需求极阅。
為什么不用NSUserDefault來保存用戶名和密碼呢鱼冀?因為NSUserDefault可以在資料沙盒中找到崩掘。
對應(yīng)的沙盒路徑:
Library -> Preferences -> bundleId.plist
只要找到這個文件,儲存在里面的信息便被盜取。
另外纺酸,存在KeyChain里的信息是不會隨APP被刪除而刪除的嘲碱,還可以支持iCloud同步金砍。
api
用到的api有以下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)
查詢:
NSMutableDictionary *query = [NSMutableDictionary new];
[query setValue:service forKey:(__bridge id)kSecAttrService]; //標(biāo)識
[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];//設(shè)置返回數(shù)據(jù)
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
增加:
NSMutableDictionary *query = [NSMutableDictionary new];
[query setValue:service forKey:(__bridge id)kSecAttrService]; //標(biāo)識
[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);
更新:
NSMutableDictionary *query = [NSMutableDictionary new];
[query setValue:service forKey:(__bridge id)kSecAttrService]; //標(biāo)識
[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);
刪除:
NSMutableDictionary *query = [NSMutableDictionary new];
[query setValue:service forKey:(__bridge id)kSecAttrService]; //標(biāo)識
[query setValue:account forKey:(__bridge id)kSecAttrAccount];//賬戶
[query setValue:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; //儲存密碼
OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query);