- Demo
- KeyChain基础
- 为什么使用KeyChain呢?
第一个原因:安全性高。在iOS中保存数据的方式有很多,类如NSUserDefaults、plist文件保存、数据库等。但是这些方式的安全性都不高,如果是普通数据还可以使用,但如果要保存密码、序列号、证书等敏感信息时,那些方式就显得不太安全了。这时就需要用到KeyChain了。
第二个原因:Keychain里保存的信息不会因App被删除而丢失。Keychain的信息是存在于每个应用(app)的沙盒之外的,所以keychain里保存的信息不会因App被删除而丢失,在用户重新安装App后依然有效,数据还在。 - 如何使用(这里以保存用户名和密码为例)
第一步:新建一个类
#import <Foundation/Foundation.h>
#import <Security/Security.h>
@interface SZYKeychain : NSObject
+(void)saveKeychain:(NSString *)service withData:(id)data;
+(id)loadKeychain:(NSString *)service;
+(void)deleteKeyChain:(NSString *)service;
@end
第二步:实现方法
//
// SZYKeychain.m
// Keychain_Demo
//
// Created by apple on 16/6/1.
// Copyright © 2016年 apple. All rights reserved.
//
#import "SZYKeychain.h"
@implementation SZYKeychain
+(NSMutableDictionary *)getKeychainQuery:(NSString *)service {
return [NSMutableDictionary dictionaryWithObjectsAndKeys:
(__bridge_transfer id)kSecClassGenericPassword,(__bridge_transfer id)kSecClass,
service,(__bridge_transfer id)kSecAttrService,
service,(__bridge_transfer id)kSecAttrAccount,
(__bridge_transfer id)kSecAttrAccessibleAfterFirstUnlock,(__bridge_transfer id)kSecAttrAccessible,
nil];
}
+(void)saveKeychain:(NSString *)service withData:(id)data {
NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery);
[keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data]
forKey:(__bridge_transfer id)kSecValueData];
SecItemAdd((__bridge_retained CFDictionaryRef)keychainQuery, NULL);
}
+(id)loadKeychain:(NSString *)service {
id ret = nil;
NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
[keychainQuery setObject:(id)kCFBooleanTrue
forKey:(__bridge_transfer id)kSecReturnData];
[keychainQuery setObject:(id)kSecMatchLimitOne
forKey:(__bridge_transfer id)kSecMatchLimit];
CFDataRef keyData = NULL;
if (SecItemCopyMatching((__bridge_retained CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
@try {
ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge_transfer NSData *)keyData];
}
@catch (NSException *exception) {
NSLog(@"Unarchive of %@ failed:%@",service, exception);
}
@finally {
}
}
return ret;
}
+(void)deleteKeyChain:(NSString *)service {
NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery);
}
@end
第三步:使用
定义几个Key
static NSString *const kSZYKeyChain_USERNAME_PASSWORD = @"cc.suzhenyu.usernamepassword";
static NSString *const kSZYKeyChain_USERNAME = @"cc.suzhenyu.username";
static NSString *const kSZYKeyChain_PASSWORD = @"cc.suzhenyu.password";
存:
NSMutableDictionary *dataDict = [[NSMutableDictionary alloc] init];
[dataDict setObject:username forKey:kSZYKeyChain_USERNAME];
[dataDict setObject:password forKey:kSZYKeyChain_PASSWORD];
[SZYKeychain saveKeychain:kSZYKeyChain_USERNAME_PASSWORD withData:dataDict];
取:
NSMutableDictionary *dataDict = (NSMutableDictionary *)[SZYKeychain loadKeychain:kSZYKeyChain_USERNAME_PASSWORD];
NSLog(@"username:%@,password:%@",[dataDict objectForKey:kSZYKeyChain_USERNAME],[dataDict objectForKey:kSZYKeyChain_PASSWORD]);
删:
[SZYKeychain deleteKeyChain:kSZYKeyChain_USERNAME_PASSWORD];
参考资料: