引
有用戶就用用戶名和密碼,而現在的應用都少不了一個保存用戶名和密碼用于自動登錄的功能,本文介紹使用iOS自帶的Keychain方法保存用戶名和密碼。
說到保存用戶名和密碼,以前有用過本地的數據庫來保存,也接觸過用userdefault來保存,后來在一個項目中發現了一個新的方法——用Keychain來保存。用過mac的人都不會對鑰匙串感到陌生,這也是一個鑰匙串,比起用數據庫或者userdefault什么的來保存,這種方法會更安全一些,而且保存的內容不會隨著應用的更新等刪除,可以始終保存在沙盒中。這個方法還有一個優勢,就是可以讓用戶名和密碼在不同應用之間使用,一次保存,多次使用,這里推測一下,不知道使用第三方登錄功能是不是用這個來實現的呢。一般自動登錄不外乎對用戶名和密碼的保存、讀取和修改,這里也主要講這個三個功能的實現。
1、準備工作
要使用Keychain來操作,前期的準備還是有點麻煩的,因為不是直接可以拿來用的,而需要在工程中額外添加一些東西:
1)、導入secutity.framework
第一步需要額外導入一個安全框架,導入方法如下:
先在左側文件列表中選中項目名稱,然后選中TARGETS,中間界面選中Build Phases,在Link Binary With Libraries中點擊加號,搜索找到secutity.framework導入即可:
這樣就把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,如下:
這樣再運行就不會出錯了。
以上是準備工作,接下來進入代碼。
2、使用Keychain保存用戶名與密碼
一般在應用的登錄界面都會有保存用戶名和密碼的選項,這里我們模擬一下,在界面中放兩個輸入框用來輸入用戶名和密碼,然后一個登錄按鈕來實現跳轉和保存,界面如下:
把輸入框和按鈕都關聯到我們的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的操作:
- 這里是創建了一個keychain的對象,用來保存用戶名和密碼,創建的過程中有兩個參數,一個是Identifier,這個參數是一個字符串,用來標識keychain,以后都根據這個標識來找到這里保存的內容;第二個是創建組,如果要在多個應用中使用Keychain,就要設置這個參數,是組的標識,這里我們只在本應用使用,就設為nil。Keychain還有很多屬性可以設置,這里是最簡單的用法,基本可以滿足需求,如果想了解更多,可以繼續查找資料了解。
- 我們的目的就是保存用戶名和密碼,Keychain保存非常簡單,這一句代碼就把用戶名保存進去了,Keychain自己帶有一些key值,各有各的用處,最常用的就是保存用戶名和密碼的,一般我們保存用戶名就是放在這個Key中就好了。
- 同2一樣,一般我們保存密碼就是放在這個Key中的。除了這兩個以外,還有一些其他的Key,有興趣的可以繼續了解。
這樣我們就將用戶名和密碼保存在Keychain中了,非常簡單吧。
3、獲取用戶名和密碼
在一般的思路中,第一次登陸成功后,我們將已經驗證正確的用戶名和密碼保存在keychain里,以后每次打開應用,我們就應該從keychain中獲取曾經保存的用戶名和密碼來通過驗證而不需要用戶再次輸入,對吧,要讀取也非常簡單,我們先創建一個界面,放兩個Label用來在登錄后從keychain中獲取用戶名和密碼并顯示出來,如下:
其實獲取和保存就是兩個相反的過程,也就是先通過之前保存時設的標識找到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;
}
一目了然,跟保存幾乎一樣只是設置變成了讀取,這樣就可以輸入什么,顯示什么了:
4、修改keychain中的值
一般有用戶的應用,都會提供修改密碼的功能,如果用戶登錄后修改了密碼,我們總不能要求用戶退出登錄重新登錄一次才能保存密碼對吧,另一個情況,如果用戶換了一個賬號登錄,那就是用戶名和密碼都改了,所以修改keychain中的值也是一個比較常用的功能。我們在界面中加一個新密碼的輸入框,加一個修改密碼的按鈕,再加一個顯示新密碼的Label,如圖:
其實修改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];// 收起鍵盤
}
這樣就可以修改了,再次獲取的時候就是新設的值了,如下:
Keychain要完全了解,還是比較復雜的,但是最常用的功能,其實也就上面這些了,用起來非常簡單方便,以后有機會再詳細了解更多的內容吧。
這里可以下載到我的示例工程:https://github.com/Cloudox/KeyChainTest