项目中需要保存用户密码,以实现自动登录的功能。于是,研究了下iOS保存密码的方法:
作为一名iPhone开发者,你需要对你的用户安全负责。请问,你是怎么保存用户的密码的?直接保存到plist文件里?加密?AES? DES?能保证你的代码不被反编译拿到你的加密Key?
这也未免太不苹果了吧。我Google了一下,国内的开发者根本没有注意到这个问题。
苹果系统中有个程序叫"钥匙串"(Keychain),它不仅仅是你申请开发证书用的。哈哈,它可以存密码!这也是苹果给出的保存密码的最佳解决方案。
通常情况下,我们用NSUserDefaults存储数据信息,但是对于一些私密信息,比如密码、证书等等,就需要使用更为安全的keychain了。
如何在应用里使用keyChain?我们需要导入Security.framework ,keychain的操作接口声明在头文件SecItem.h里。直接使用SecItem.h里方法操作keychain,需要写的代码较为复杂。用原生的Security.framework就可以实现钥匙串的访问、读写,但是只能在真机上进行,模拟器会出错。为减轻咱们程序员的开发,我们可以使用一些在Github上已经封装好了的工具类,让你既能在模拟器又能在真机上访问钥匙串。比如:SFHFKeychainUtils和KeychainItemWrapper,这里主要介绍SFHFKeychainUtils的使用。
+ (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error; + (BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error; + (BOOL) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error;
#import <UIKit/UIKit.h> @interface ViewController : UIViewController @property (nonatomic, strong) NSString *userName; @property (nonatomic, strong) NSString *userPassword; @property (nonatomic, strong) NSString *serviceName; //本条keychains所属的服务(组) - (IBAction)savePassword:(id)sender; - (IBAction)getPassword:(id)sender; - (IBAction)deletePassword:(id)sender; @endViewController.m的代码为:
#import "ViewController.h" #import "SFHFKeychainUtils.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (IBAction)savePassword:(id)sender { self.userName = @"[email protected]"; self.userPassword = @"123456"; self.serviceName = @"com.china.TestKeyChain"; //本条keychains所属的服务(组) NSError *error; BOOL saved = [SFHFKeychainUtils storeUsername:self.userName andPassword:self.userPassword forServiceName:self.serviceName updateExisting:YES error:&error]; if (!saved) { NSLog(@"❌Keychain保存密码时出错:%@", error); }else{ NSLog(@"✅Keychain保存密码成功!"); } } - (IBAction)getPassword:(id)sender { self.userName = @"[email protected]"; self.userPassword = @"123456"; self.serviceName = @"com.china.TestKeyChain"; //本条keychains所属的服务(组) NSError *error; NSString * string = [SFHFKeychainUtils getPasswordForUsername:self.userName andServiceName:self.serviceName error:&error]; if (!string) { self.userPassword = string; } if(error || !string){ NSLog(@"❌从Keychain里获取密码出错:%@", error); } else{ NSLog(@"✅从Keychain里获取密码成功!密码为%@",self.userPassword); } } - (IBAction)deletePassword:(id)sender { self.userName = @"[email protected]"; self.userPassword = @"123456"; self.serviceName = @"com.china.TestKeyChain"; //本条keychains所属的服务(组) NSError *error; BOOL isDeleted; isDeleted = [SFHFKeychainUtils deleteItemForUsername:self.userName andServiceName:self.serviceName error:&error]; if (!isDeleted) { NSLog(@"❌Keychain删除