iOS提供一種安全的存儲數據的方式丽旅,就是鑰匙串,想要在app中使用鑰匙串纺棺,首先要開啟鑰匙串訪問的功能榄笙,即在app server中勾選Data Protection功能,就像要通知一樣祷蝌,需要開啟改功能茅撞。如下圖:
同時使用精準app ID如下圖:
打開電腦鑰匙串,察看存儲在鑰匙串數據巨朦,如圖米丘,ios和mac是相似的。
對應的屬性
kSecClass-- 上圖中的種類
kSecAttrService--上圖中的位置
kSecAttrAccount--上圖中的賬戶
kSecValueData--上圖中的密碼
添加數據:SecItemAdd
NSString *key = @"pwd";
NSString *value = @"password";
NSData *valueData = [value dataUsingEncoding:NSUTF8StringEncoding];
NSString *service = [[NSBundle mainBundle] bundleIdentifier];
NSDictionary *dict = @{
(__bridge id)kSecClass:(__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService:service,
(__bridge id)kSecAttrAccount:key,
(__bridge id)kSecValueData:valueData
};
CFTypeRef typeResult = NULL;
OSStatus state = SecItemAdd((__bridge CFDictionaryRef)dict, &typeResult);
if (state == errSecSuccess) {
NSLog(@"store secceed");
}
查詢屬性:SecItemCopyMatching
//查找
-(void)findAttr
{
NSString *key = @"pwd";
NSString *service = [[NSBundle mainBundle] bundleIdentifier];
NSDictionary *dict = @{
(__bridge id)kSecClass:(__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService:service,
(__bridge id)kSecAttrAccount:key,
(__bridge id)kSecReturnAttributes:(__bridge id)kCFBooleanTrue
};
CFDictionaryRef resultDict = NULL;
OSStatus state = SecItemCopyMatching((__bridge CFDictionaryRef)dict, (CFTypeRef*)&resultDict);
NSDictionary *result = (__bridge_transfer NSDictionary*)resultDict;
if (state == errSecSuccess)
{
NSLog(@"server:%@",result[(__bridge id)kSecAttrService]);
NSLog(@"account:%@",result[(__bridge id)kSecAttrAccount]);
NSLog(@"assessGroup:%@",result[(__bridge id)kSecAttrAccessGroup]);
NSLog(@"createDate:%@",result[(__bridge id)kSecAttrCreationDate]);
NSLog(@"modifyDate:%@",result[(__bridge id)kSecAttrModificationDate]);
}
}
當在字典中添加kSecReturnAttributes并設置為yes時糊啡,表示查詢鑰匙串數據的屬性拄查,SecItemCopyMatching的第二個參數為字典。
查詢數據:SecItemCopyMatching
//查找數據
-(void)findData
{
NSString *key = @"pwd";
NSString *server = [[NSBundle mainBundle] bundleIdentifier];
NSDictionary *queueDict = @{
(__bridge id)kSecClass:(__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService:server,
(__bridge id)kSecAttrAccount:key,
(__bridge id)kSecReturnData:(__bridge id)kCFBooleanTrue
/*(__bridge id)kSecMatchLimit : (__bridge id)kSecMatchLimitAll
當為kSecMatchLimit時棚蓄,SecItemCopyMatching第二個參數為CFArrayRef堕扶,元素為CFDataRef*/
};
CFDataRef dataRef = NULL;
OSStatus state = SecItemCopyMatching((__bridge CFDictionaryRef)queueDict, (CFTypeRef*)&dataRef);
if (state == errSecSuccess) {
NSString *value = [[NSString alloc] initWithData:(__bridge_transfer NSData*)dataRef encoding:NSUTF8StringEncoding];
NSLog(@"value:%@",value);
}
}
當在字典中添加kSecReturnData并設置為yes時,表示查詢鑰匙串數據的數據癣疟,SecItemCopyMatching的第二個參數為CFDataRef挣柬。當在字典中添加了kSecMatchLimit 時并設置為kSecMatchLimitAll會返回所有的,SecItemCopyMatching第二個參數為CFArrayRef睛挚,元素為CFDataRef。
更新數據:SecItemUpdate
-(void)updateData
{
NSString *key = @"pwd";
NSString *server = [[NSBundle mainBundle] bundleIdentifier];
NSDictionary *queue = @{
(__bridge id)kSecClass:(__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService:server,
(__bridge id)kSecAttrAccount:key
};
OSStatus state = SecItemCopyMatching((__bridge CFDictionaryRef)queue, NULL);
//存在修改
if (state == errSecSuccess) {
NSString *newValue = @"new Value";
NSData *newData = [newValue dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *paramDict = @{
(__bridge id)kSecValueData:newData
};
OSStatus updateState = SecItemUpdate((__bridge CFDictionaryRef)queue, (__bridge CFDictionaryRef)paramDict);
if (updateState == errSecSuccess) {
NSLog(@"更新成功");
}
}
}
刪除鑰匙串:SecItemDelete
-(void)deleteData
{
NSString *key = @"pwd";
NSString *server = [[NSBundle mainBundle] bundleIdentifier];
NSDictionary *queue = @{
(__bridge id)kSecClass:(__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService:server,
(__bridge id)kSecAttrAccount:key
};
OSStatus state = SecItemCopyMatching((__bridge CFDictionaryRef)queue, NULL);
//存在
if (state == errSecSuccess) {
OSStatus deleteState = SecItemDelete((__bridge CFDictionaryRef)queue);
if (deleteState == errSecSuccess) {
NSLog(@"刪除成功!!!");
}
}
}
總結:鑰匙串使用感覺還是挺有用的急黎,今天特意研究了一下扎狱,還有兩個同一個開發(fā)者發(fā)布的app之間可以共享鑰匙串數據,Sharing Keychain Data Between Multiple Apps勃教,下次有時間研究一下淤击,下次再更新。
簡單demo:https://github.com/jiangtaidi/KeyChainPro.git