iOS中保存密码,如果要追求安全性,那么使用苹果自带的Keychain Services无疑是最佳选择。如果要在程序中使用Keychain Services,首先要添加Security.framework。
Keychain Services提供了一系列api用以存取和更新keychain item:
SecItemAdd(添加)
SecItemUpdate(更新)
SecItemCopyMatching(查找)
SecItemDelete(删除)
这些方法直接使用有点麻烦,需要进行面向对象的封装。我写了一个简单的例子,只是用来保存用户名和密码,以实现记住密码这项功能。
下面贴一部分代码,完整项目下载:https://github.com/tenric/KeyChainDemo
MyKeyChainHelper.h
#import <Foundation/Foundation.h> @interface MyKeyChainHelper : NSObject + (void) saveUserName:(NSString*)userName userNameService:(NSString*)userNameService psaaword:(NSString*)pwd psaawordService:(NSString*)pwdService; + (void) deleteWithUserNameService:(NSString*)userNameService psaawordService:(NSString*)pwdService; + (NSString*) getUserNameWithService:(NSString*)userNameService; + (NSString*) getPasswordWithService:(NSString*)pwdService; @end
MyKeyChainHelper.m
#import "MyKeyChainHelper.h" @implementation MyKeyChainHelper + (NSMutableDictionary *)getKeyChainQuery:(NSString *)service { return [NSMutableDictionary dictionaryWithObjectsAndKeys: (id)kSecClassGenericPassword,(id)kSecClass, service, (id)kSecAttrService, service, (id)kSecAttrAccount, (id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible, nil]; } + (void) saveUserName:(NSString*)userName userNameService:(NSString*)userNameService psaaword:(NSString*)pwd psaawordService:(NSString*)pwdService { NSMutableDictionary *keychainQuery = [self getKeyChainQuery:userNameService]; SecItemDelete((CFDictionaryRef)keychainQuery); [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:userName] forKey:(id)kSecValueData]; SecItemAdd((CFDictionaryRef)keychainQuery, NULL); keychainQuery = [self getKeyChainQuery:pwdService]; SecItemDelete((CFDictionaryRef)keychainQuery); [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:pwd] forKey:(id)kSecValueData]; SecItemAdd((CFDictionaryRef)keychainQuery, NULL); } + (void) deleteWithUserNameService:(NSString*)userNameService psaawordService:(NSString*)pwdService { NSMutableDictionary *keychainQuery = [self getKeyChainQuery:userNameService]; SecItemDelete((CFDictionaryRef)keychainQuery); keychainQuery = [self getKeyChainQuery:pwdService]; SecItemDelete((CFDictionaryRef)keychainQuery); } + (NSString*) getUserNameWithService:(NSString*)userNameService { NSString* ret = nil; NSMutableDictionary *keychainQuery = [self getKeyChainQuery:userNameService]; [keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; [keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit]; CFDataRef keyData = NULL; if (SecItemCopyMatching((CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) { @try { ret = [NSKeyedUnarchiver unarchiveObjectWithData:(NSData *)keyData]; } @catch (NSException *e) { NSLog(@"Unarchive of %@ failed: %@", userNameService, e); } @finally { } } if (keyData) CFRelease(keyData); return ret; } + (NSString*) getPasswordWithService:(NSString*)pwdService { NSString* ret = nil; NSMutableDictionary *keychainQuery = [self getKeyChainQuery:pwdService]; [keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; [keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit]; CFDataRef keyData = NULL; if (SecItemCopyMatching((CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) { @try { ret = [NSKeyedUnarchiver unarchiveObjectWithData:(NSData *)keyData]; } @catch (NSException *e) { NSLog(@"Unarchive of %@ failed: %@", pwdService, e); } @finally { } } if (keyData) CFRelease(keyData); return ret; } @end