keyChain保存用户名和密码
iOS的keychain服务提供了一种安全的保存私密信息(密码,序列号,证书等)的方式,每个ios程序都有一个独立的keychain存储。相对于NSUserDefaults、文件保存等一般方式,keychain保存更为安全,而且keychain里保存的信息不会因App被删除而丢失,所以在重装App后,keychain里的数据还能使用。
下面贴上自己封装的keyChain保存用户登录名和密码的代码:
WQKeyChain.h
#import <Foundation/Foundation.h>
@interface WQKeyChain : NSObject
/**
* 保存数据
*
* @param service 标识符; eg: @"com.公司名.app.allInfo"
* @param data 保存的数据; eg:保存账号密码时,该参数可以是一个包含用户名和密码的字典
*/
+ (void)saveWithServie:(NSString *)service data:(id)data;
/**
* 根据标示符读取保存的数据
*
* @param service 标识符;
*
* @return 返回保存的数据;
*/
+ (id)loadDataWithService:(NSString *)service;
/**
* 根据标识符删除保存的数据
*
* @param service 标识符;
*/
+ (void)deleteDataWithService:(NSString *)service;
@end
WQKeyChain.m
#import "WQKeyChain.h"
@implementation WQKeyChain
// 保存数据
+ (void)saveWithServie:(NSString *)service data:(id)data
{
// 1.先根据标识符获取keyChainQuery
NSMutableDictionary *keyChainQuery = [self getKeychainQuery:service];
// 2.删除旧数据
SecItemDelete((__bridge_retained CFDictionaryRef)keyChainQuery);
// 3.添加新数据
[keyChainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:((__bridge_transfer id)kSecValueData)];
// 添加keyChainQuery到keychain
SecItemAdd((__bridge_retained CFDictionaryRef)keyChainQuery, NULL);
}
// 根据标示符读取保存的数据
+ (id)loadDataWithService:(NSString *)service
{
id returnData = nil;
// 1.先根据标识符获取keyChainQuery
NSMutableDictionary *keyChainQuery = [self getKeychainQuery:service];
// 2. 配置keyChainQuery的设置
[keyChainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge_transfer id)kSecReturnData];
[keyChainQuery setObject:(__bridge_transfer id)kSecMatchLimitOne forKey:(__bridge_transfer id)kSecMatchLimit];
CFDataRef keyData = nil;
if (SecItemCopyMatching((__bridge_retained CFDictionaryRef)keyChainQuery, (CFTypeRef *)&keyData) == noErr) {
@try {
returnData = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge_transfer NSData *)keyData];
}
@catch (NSException *exception) {
NSLog(@"Unarchive of %@ failed: %@", service, exception);
}
@finally {
}
}
return returnData;
}
// 根据标识符删除保存的数据
+ (void)deleteDataWithService:(NSString *)service
{
// 1.先根据标识符获取keyChainQuery
NSMutableDictionary *keyChainQuery = [self getKeychainQuery:service];
// 2.删除
SecItemDelete((__bridge_retained CFDictionaryRef)keyChainQuery);
}
#pragma mark - private 私有方法
// 从keyChain根据标识符获取keyChainQuery
+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
NSMutableDictionary *dictionary = [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];
return dictionary;
}
@end
#import "WQKeyChain.h"
@implementation WQKeyChain
// 保存数据
+ (void)saveWithServie:(NSString *)service data:(id)data
{
// 1.先根据标识符获取keyChainQuery
NSMutableDictionary *keyChainQuery = [self getKeychainQuery:service];
// 2.删除旧数据
SecItemDelete((__bridge_retained CFDictionaryRef)keyChainQuery);
// 3.添加新数据
[keyChainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:((__bridge_transfer id)kSecValueData)];
// 添加keyChainQuery到keychain
SecItemAdd((__bridge_retained CFDictionaryRef)keyChainQuery, NULL);
}
// 根据标示符读取保存的数据
+ (id)loadDataWithService:(NSString *)service
{
id returnData = nil;
// 1.先根据标识符获取keyChainQuery
NSMutableDictionary *keyChainQuery = [self getKeychainQuery:service];
// 2. 配置keyChainQuery的设置
[keyChainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge_transfer id)kSecReturnData];
[keyChainQuery setObject:(__bridge_transfer id)kSecMatchLimitOne forKey:(__bridge_transfer id)kSecMatchLimit];
CFDataRef keyData = nil;
if (SecItemCopyMatching((__bridge_retained CFDictionaryRef)keyChainQuery, (CFTypeRef *)&keyData) == noErr) {
@try {
returnData = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge_transfer NSData *)keyData];
}
@catch (NSException *exception) {
NSLog(@"Unarchive of %@ failed: %@", service, exception);
}
@finally {
}
}
return returnData;
}
// 根据标识符删除保存的数据
+ (void)deleteDataWithService:(NSString *)service
{
// 1.先根据标识符获取keyChainQuery
NSMutableDictionary *keyChainQuery = [self getKeychainQuery:service];
// 2.删除
SecItemDelete((__bridge_retained CFDictionaryRef)keyChainQuery);
}
#pragma mark - private 私有方法
// 从keyChain根据标识符获取keyChainQuery
+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
NSMutableDictionary *dictionary = [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];
return dictionary;
}
@end
用户管理类
UserDataManager.h
#import <Foundation/Foundation.h>
@interface UserDataManager : NSObject
/**
* 保存用户信息
*
* @param userName 用户名
* @param password 密码
*/
+ (void)saveUserInfoWithUserName:(NSString *)userName password:(NSString *)password;
/**
* 读取用户名
*
* @return 用户名字符串
*/
+ (NSString *)loadUserName;
/**
* 读取密码
*
* @return 密码字符串
*/
+ (NSString *)loadPassword;
/**
* 删除用户信息
*/
+ (void)deleteUserInfo;
@end
#import <Foundation/Foundation.h>
@interface UserDataManager : NSObject
/**
* 保存用户信息
*
* @param userName 用户名
* @param password 密码
*/
+ (void)saveUserInfoWithUserName:(NSString *)userName password:(NSString *)password;
/**
* 读取用户名
*
* @return 用户名字符串
*/
+ (NSString *)loadUserName;
/**
* 读取密码
*
* @return 密码字符串
*/
+ (NSString *)loadPassword;
/**
* 删除用户信息
*/
+ (void)deleteUserInfo;
@end
UserDataManager.m
#import "UserDataManager.h"
#import "WQKeyChain.h"
@implementation UserDataManager
static NSString *const KEY_IN_KEYCHAIN = @"com.companyName.app.allinfo";
static NSString *const KEY_USERNAME = @"com.companyName.app.userName";
static NSString *const KEY_PASSWORD = @"com.companyName.app.password";
// 保存用户信息
+ (void)saveUserInfoWithUserName:(NSString *)userName password:(NSString *)password
{
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setObject:userName forKey:KEY_USERNAME];
[dic setObject:password forKey:KEY_PASSWORD];
[WQKeyChain saveWithServie:KEY_IN_KEYCHAIN data:dic];
}
// 读取用户名
+ (NSString *)loadUserName
{
NSMutableDictionary *dic = [WQKeyChain loadDataWithService:KEY_IN_KEYCHAIN];
return [dic objectForKey:KEY_USERNAME];
}
// 读取密码
+ (NSString *)loadPassword
{
NSMutableDictionary *dic = [WQKeyChain loadDataWithService:KEY_IN_KEYCHAIN];
return [dic objectForKey:KEY_PASSWORD];
}
// 删除用户信息
+ (void)deleteUserInfo
{
[WQKeyChain deleteDataWithService:KEY_IN_KEYCHAIN];
}
@end
这里是对登录名和密码进行简单的本地存储,网上还有一些写的比较全的博客,这里附上链接:
点击打开链接