使用 keychain 来存储, 也就是钥匙串, 使用 keychain 需要导入 Security 框架
iOS 的 keychain 服务提供了一种安全的保存私密信息(密码,序列号,证书等)的方式,每个 ios 程序都有一个独立的 keychain 存储。相对于 NSUserDefaults、文件保存等一般方式,keychain 保存更为安全,而且 keychain 里保存的信息不会因 App 被删除而丢失,所以在 重装 App 后,keychain 里的数据还能使用。从 ios 3。0 开始,跨程序分享 keychain 变得可行。
如何需要在应用里使 用使用 keyChain,我们需要导入 Security.framework,keychain 的操作接口声明在头文件 SecItem.h 里。直接使用 SecItem.h 里方法操作 keychain,需要写的代码较为复杂,为减轻 咱们程序员的开发,我们可以使用一些已经封装好了的工具类,下面我会简单介绍下我用过的两个工具类:KeychainItemWrapper 和 SFHFKeychainUtils。
自定义一个 keychain 的类
CSKeyChain.h
@interface CSKeyChain : NSObject
+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service;
+ (void)save:(NSString *)service data:(id)data;
+ (id)load:(NSString *)service;
+ (void)delete:(NSString *)service;
@end
CSKeyChain.m
#import “CSKeyChain.h”
#import<Security/Security.h>
@implementation CSKeyChain
+ (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)save:(NSString *)service data:(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)load:(NSString *)service {
id ret = nil;
NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
// 配置搜索设置
[keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge_transfer id)kSecReturnData];
[keychainQuery setObject:(__bridge_transfer 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 *e) {
NSLog(@”Unarchive of %@ failed: %@”, service, e);
} @finally {
}
}
return ret;
}
+ (void)delete:(NSString *)service {
NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery);
}
@end
在别的类实现存储, 加载, 删除敏感信息方法
// 用来标识这个钥匙串
static NSString * const KEY_IN_KEYCHAIN = @”com.cs.app.allinfo”;
// 用来标识密码
static NSString * const KEY_PASSWORD = @”com.cs.app.password”;
+ (void)savePassWord:(NSString *)password {
NSMutableDictionary *passwordDict = [NSMutableDictionary dictionary];
[passwordDict setObject:password forKey:KEY_PASSWORD];
[CSKeyChain save:KEY_IN_KEYCHAIN data:passwordDict];
}
+ (id)readPassWord {
NSMutableDictionary *passwordDict = (NSMutableDictionary *)[CSKeyChain load:KEY_IN_KEYCHAIN];
return [passwordDict objectForKey:KEY_PASSWORD];
}
+ (void)deletePassWord {
[CSKeyChain delete:KEY_IN_KEYCHAIN];
}
原文更多:iOS 面试题大全