iOS中Keychain保存用户名和密码

有用户就用用户名和密码,而现在的应用都少不了一个保存用户名和密码用于自动登录的功能,本文介绍使用iOS自带的Keychain方法保存用户名和密码。

说到保存用户名和密码,以前有用过本地的数据库来保存,也接触过用userdefault来保存,后来在一个项目中发现了一个新的方法——用Keychain来保存。用过mac的人都不会对钥匙串感到陌生,这也是一个钥匙串,比起用数据库或者userdefault什么的来保存,这种方法会更安全一些,而且保存的内容不会随着应用的更新等删除,可以始终保存在沙盒中。这个方法还有一个优势,就是可以让用户名和密码在不同应用之间使用,一次保存,多次使用,这里推测一下,不知道使用第三方登录功能是不是用这个来实现的呢。一般自动登录不外乎对用户名和密码的保存、读取和修改,这里也主要讲这个三个功能的实现。

1、准备工作

要使用Keychain来操作,前期的准备还是有点麻烦的,因为不是直接可以拿来用的,而需要在工程中额外添加一些东西:

1)、导入secutity.framework

第一步需要额外导入一个安全框架,导入方法如下:

先在左侧文件列表中选中项目名称,然后选中TARGETS,中间界面选中Build Phases,在Link Binary With Libraries中点击加号,搜索找到secutity.framework导入即可:

image
image

这样就把secutity.framework导入到了我们的工程中来。

2)、添加KeychainItemWrapper.h/.m文件

除了secutity.framework,我们还要添加一个东西到工程中,就是KeychainItemWrapper.h和KeychainItemWrapper.m文件,这两个也需要额外引入才能在我们自己的代码中引用,就当成是引用第三方类库一样吧,这两个文件直接复制进工程里面就好了,可以在我的示例工程中复制。

3)、禁用KeychainItemWrapper.h/.m文件的ARC

现在已经流行ARC机制,我们创建工程也是默认的全局使用ARC,但是这两个文件因为年代久远吧,还不是ARC而是MRC,可以在其代码中看到大量MRC的内容比如release之类的,如果不加修改,直接运行会报很多错误,所以有两个解决办法,第一个把所有报错的地方由MRC方式改成ARC方式,这种方法太麻烦,第二种就是直接禁用这个文件的ARC就好了,方法如下:

先在左侧文件列表中选中项目名称,然后选中TARGETS,中间界面选中Build Phases,然后在Compile Sources中找到要禁用的文件,这里是KeychainItemWrapper.m,然后双击修改其Compiler Flags值为 -fno-objc-arc,如下:

image

这样再运行就不会出错了。

以上是准备工作,接下来进入代码。

2、使用Keychain保存用户名与密码

一般在应用的登录界面都会有保存用户名和密码的选项,这里我们模拟一下,在界面中放两个输入框用来输入用户名和密码,然后一个登录按钮来实现跳转和保存,界面如下:

image

把输入框和按钮都关联到我们的ViewController中去,然后在登录按钮的响应方法中实现保存功能,注意,在我们的ViewController中要导入Keychain文件才能正常使用:

// ViewController.m中  
#import "KeychainItemWrapper.h"  
  
- (IBAction)login:(id)sender {  
    NSString *username = self.usernameLabel.text;// 获取输入的用户名  
    NSString *password = self.passwordLabel.text;// 获取输入的密码  
    if (![username isEqualToString:@""] && ![password isEqualToString:@""]) {// 非空则保存  
        KeychainItemWrapper *keychain = [[KeychainItemWrapper alloc] initWithIdentifier:@"Login" accessGroup:nil];// 1  
        [keychain setObject:username forKey:(__bridge id)(kSecAttrAccount)];// 2  
        [keychain setObject:password forKey:(__bridge id)(kSecValueData)];// 3  
    }  
}  

其他的不用多说,主要说说三行Keychain的操作:

  1. 这里是创建了一个keychain的对象,用来保存用户名和密码,创建的过程中有两个参数,一个是Identifier,这个参数是一个字符串,用来标识keychain,以后都根据这个标识来找到这里保存的内容;第二个是创建组,如果要在多个应用中使用Keychain,就要设置这个参数,是组的标识,这里我们只在本应用使用,就设为nil。Keychain还有很多属性可以设置,这里是最简单的用法,基本可以满足需求,如果想了解更多,可以继续查找资料了解。
  2. 我们的目的就是保存用户名和密码,Keychain保存非常简单,这一句代码就把用户名保存进去了,Keychain自己带有一些key值,各有各的用处,最常用的就是保存用户名和密码的,一般我们保存用户名就是放在这个Key中就好了。
  3. 同2一样,一般我们保存密码就是放在这个Key中的。除了这两个以外,还有一些其他的Key,有兴趣的可以继续了解。

这样我们就将用户名和密码保存在Keychain中了,非常简单吧。

3、获取用户名和密码

在一般的思路中,第一次登陆成功后,我们将已经验证正确的用户名和密码保存在keychain里,以后每次打开应用,我们就应该从keychain中获取曾经保存的用户名和密码来通过验证而不需要用户再次输入,对吧,要读取也非常简单,我们先创建一个界面,放两个Label用来在登录后从keychain中获取用户名和密码并显示出来,如下:

image

其实获取和保存就是两个相反的过程,也就是先通过之前保存时设的标识找到keychain,然后获取对应Key的内容:

// InfoViewController.m中  
#import "KeychainItemWrapper.h"  
  
- (void)viewDidLoad {  
    [super viewDidLoad];  
    // Do any additional setup after loading the view.  
    KeychainItemWrapper *keychain = [[KeychainItemWrapper alloc] initWithIdentifier:@"Login" accessGroup:nil];// 通过同样的标志创建keychain  
    // 获取对应Key里保存的用户名和密码  
    NSString *username = [keychain objectForKey:(__bridge id)(kSecAttrAccount)];  
    NSString *password = [keychain objectForKey:(__bridge id)(kSecValueData)];  
    // 显示  
    self.usernameLabel.text = username;  
    self.passwordLabel.text = password;  
}  

一目了然,跟保存几乎一样只是设置变成了读取,这样就可以输入什么,显示什么了:

image

4、修改keychain中的值

一般有用户的应用,都会提供修改密码的功能,如果用户登录后修改了密码,我们总不能要求用户退出登录重新登录一次才能保存密码对吧,另一个情况,如果用户换了一个账号登录,那就是用户名和密码都改了,所以修改keychain中的值也是一个比较常用的功能。我们在界面中加一个新密码的输入框,加一个修改密码的按钮,再加一个显示新密码的Label,如图:

image

其实修改keychain中的值也特别简单,就跟修改dictionary中的值一样,通过标识找到keychain后,重新set对应Key的值就好了:

// InfoViewController.m中  
#import "KeychainItemWrapper.h"  
  
- (IBAction)changePW:(id)sender {  
    NSString *nPW = self.nPWText.text;// 获取新密码输入框的值  
    if (![nPW isEqualToString:@""]) {// 非空则修改  
        KeychainItemWrapper *keychain = [[KeychainItemWrapper alloc] initWithIdentifier:@"Login" accessGroup:nil];// 找到keychain  
        [keychain setObject:nPW forKey:(__bridge id)(kSecValueData)];// 设置密码对应Key的值  
          
        //重新读取并显示  
        NSString *nPassword = [keychain objectForKey:(__bridge id)(kSecValueData)];  
        self.nPWLabel.text = nPassword;  
    }  
    [self.nPWText resignFirstResponder];// 收起键盘  
}  

这样就可以修改了,再次获取的时候就是新设的值了,如下:

image

Keychain要完全了解,还是比较复杂的,但是最常用的功能,其实也就上面这些了,用起来非常简单方便,以后有机会再详细了解更多的内容吧。

这里可以下载到我的示例工程:https://github.com/Cloudox/KeyChainTest


查看作者首页

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,271评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,725评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,252评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,634评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,549评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,985评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,471评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,128评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,257评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,233评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,235评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,940评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,528评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,623评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,858评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,245评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,790评论 2 339

推荐阅读更多精彩内容