iOS提供一种安全的存储数据的方式,就是钥匙串,想要在app中使用钥匙串,首先要开启钥匙串访问的功能,即在app server中勾选Data Protection功能,就像要通知一样,需要开启改功能。如下图:
屏幕快照.png
同时使用精准app ID如下图:
屏幕快照.png
打开电脑钥匙串,察看存储在钥匙串数据,如图,ios和mac是相似的。
CAA368D2-5497-492F-BF6A-37A414C5D9D6.png
对应的属性
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(@"删除成功!!!");
}
}
}
总结:钥匙串使用感觉还是挺有用的,今天特意研究了一下,还有两个同一个开发者发布的app之间可以共享钥匙串数据,Sharing Keychain Data Between Multiple Apps,下次有时间研究一下,下次再更新。
简单demo:https://github.com/jiangtaidi/KeyChainPro.git
网友评论