iOS 的keyChain


說明:

每一個keyChain的組成如圖,整體是一個字典結構.
1.kSecClass key 定義屬於那一種類型的keyChain
2.不同的類型包含不同的Attributes,這些attributes定義了這個item的具體信息
3.每個item可以包含一個密碼項來存儲對應的密碼

使用:
引入Security包,引入文件 #import <Security/Security.h>

添加

- (IBAction)add:(id)sender {
if (nameField.text.length > 0 && passwordField.text.length > 0) {
// 一個mutable字典結構存儲item信息
NSMutableDictionary* dic = [NSMutableDictionary dictionary];
// 確定所屬的類class
[dic setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];
// 設置其他屬性attributes
[dic setObject:nameField.text forKey:(id)kSecAttrAccount];
// 添加密碼 secValue 注意是object 是 NSData
[dic setObject:[passwordField.text dataUsingEncoding:NSUTF8StringEncoding] forKey:(id)kSecValueData];
// SecItemAdd
OSStatus s = SecItemAdd((CFDictionaryRef)dic, NULL);
NSLog(@"add : %ld",s);
}
}


查找

// 查找全部
- (IBAction)sel:(id)sender {
NSDictionary* query = [NSDictionary dictionaryWithObjectsAndKeys:kSecClassGenericPassword,kSecClass,
kSecMatchLimitAll,kSecMatchLimit,
kCFBooleanTrue,kSecReturnAttributes,nil];
CFTypeRef result = nil;
OSStatus s = SecItemCopyMatching((CFDictionaryRef)query, &result);
NSLog(@"se;ect all : %ld",s);
NSLog(@"%@",result);
}

// 按名稱查找
- (IBAction)sname:(id)sender {
if (nameField.text.length >0) {
// 查找條件:1.class 2.attributes 3.search option
NSDictionary* query = [NSDictionary dictionaryWithObjectsAndKeys:kSecClassGenericPassword,kSecClass,
nameField.text,kSecAttrAccount,
kCFBooleanTrue,kSecReturnAttributes,nil];
CFTypeRef result = nil;
// 先找到一個item
OSStatus s = SecItemCopyMatching((CFDictionaryRef)query, &result);
NSLog(@"select name : %ld",s); // errSecItemNotFound 就是找不到
NSLog(@"%@",result);
if (s == noErr) {
// 繼續查找item的secValue
NSMutableDictionary* dic = [NSMutableDictionary dictionaryWithDictionary:result];
// 存儲格式
[dic setObject:(id)kCFBooleanTrue forKey:kSecReturnData];
// 確定class
[dic setObject:[query objectForKey:kSecClass] forKey:kSecClass];
NSData* data = nil;
// 查找secValue
if (SecItemCopyMatching((CFDictionaryRef)dic, (CFTypeRef*)&data) == noErr) {
if (data.length)
NSLog(@"%@",[[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]);
}
}
}
}

修改

- (IBAction)update:(id)sender {
if (nameField.text.length >0 && passwordField.text.length > 0) {
// 先查找看看有沒有
NSDictionary* query = [NSDictionary dictionaryWithObjectsAndKeys:kSecClassGenericPassword,kSecClass,
nameField.text,kSecAttrAccount,
kCFBooleanTrue,kSecReturnAttributes,nil];

CFTypeRef result = nil;
if (SecItemCopyMatching((CFDictionaryRef)query, &result) == noErr)
{
// 更新后的數據,基礎是搜到的result
NSMutableDictionary* update = [NSMutableDictionary dictionaryWithDictionary:(NSDictionary*)result];
// 修改要跟新的項 注意先加后刪的class項
[update setObject:[query objectForKey:kSecClass] forKey:kSecClass];
[update setObject:[passwordField.text dataUsingEncoding:NSUTF8StringEncoding] forKey:kSecValueData];
[update removeObjectForKey:kSecClass];
#if TARGET_IPHONE_SIMULATOR
// 模擬器的都有個默認的組“test”,刪了,不然會出錯
[update removeObjectForKey:(id)kSecAttrAccessGroup];
#endif
// 得到要修改的item,根據result,但要添加class
NSMutableDictionary* updateItem = [NSMutableDictionary dictionaryWithDictionary:result];
[updateItem setObject:[query objectForKey:(id)kSecClass] forKey:(id)kSecClass];
// SecItemUpdate
OSStatus status = SecItemUpdate((CFDictionaryRef)updateItem, (CFDictionaryRef)update);
NSLog(@"update:%ld",status);

 

刪除

- (IBAction)del:(id)sender {
if (nameField.text.length >0) {
// 刪除的條件
NSDictionary* query = [NSDictionary dictionaryWithObjectsAndKeys:kSecClassGenericPassword,kSecClass,
nameField.text,kSecAttrAccount,nil];
// SecItemDelete
OSStatus status = SecItemDelete((CFDictionaryRef)query);
NSLog(@"delete:%ld",status); // // errSecItemNotFound 就是沒有
}
}

 

注意:

1.區別(標識)一個item要用kSecAttrAccount和kSecAttrService


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM