第三方SSKeychain保存用戶密碼

UDID(-[UIDevice uniqueIdentifier])在iOS7.0被禁用,一般使用UUID來作爲設備的唯一標識

獲取到UUID後,如果用NSUserDefaults存儲,當程序被卸載後重裝時,再獲得的UUID和之前就不同了。
使用keychain存儲可以保證程序卸載重裝時,UUID不變。但當刷機或者升級系統後,UUID還是會改變的。

測試發現:
程序一(test1):

    NSLog(@"--%@--", [UIDevice currentDevice].identifierForVendor.UUIDString);
    //模擬器6 8.1:   547B1AE8-483D-4740-A668-AC600A6EA7F4
    //卸載後重新運行: 547B1AE8-483D-4740-A668-AC600A6EA7F4
    //模擬器6 9.2:  4572DE5F-5E98-4C1A-A9FD-E32A12530469

程序二(test2):

    NSLog(@"--%@--", [UIDevice currentDevice].identifierForVendor.UUIDString);
    //模擬器6 8.1:   547B1AE8-483D-4740-A668-AC600A6EA7F4
    //卸載後重新運行: 547B1AE8-483D-4740-A668-AC600A6EA7F4
    //模擬器6 9.2:  4572DE5F-5E98-4C1A-A9FD-E32A12530469

1. keychain的功能



keychain的主要功能就是幫助用戶安全地記住他的密碼,keychain保存的密碼文件都是經過加密的,其它人不能直接通過打開keychain的文件獲得保存在keychain中的密碼.

蘋果已經有現成的類封裝好了keychain, KeychainItemWrapper.hKeychainItemWrapper.m文件,可以在GenericKeychain實例裏找到。

蘋果官方:Keychain Services Programming Guide

蘋果官方: Keychain Services Reference

蘋果官方代碼

>

A keychain is an encrypted container that holds passwords for multiple applications and secure services. Keychains are secure storage containers, which means that when the keychain is locked, no one can access its protected contents. In OS X, users can unlock a keychain—thus providing trusted applications access to the contents—by entering a single master password. In iOS, each application always has access to its own keychain items; the user is never asked to unlock the keychain. Whereas in OS X any application can access any keychain item provided the user gives permission, in iOS an application can access only its own keychain items.

鑰匙鏈是一個加密的容器,它保存了多個程序和安全服務的密碼。鑰匙鏈是一個安全的存儲容器,這意味着沒有應用程序或服務在它鎖住的情況下,可以訪問它的內容。在Mac OS X下,用戶可以解鎖鑰匙鏈,因此可以通過輸入主密碼的形式提供給信任的應用程序訪問裏面的內容。在iOS中,每個應用程序只能訪問自己的鑰匙鏈項;用戶不能解鎖鑰匙鏈。相反在Mac OS X裏,用戶給予了許可,每個應用程序都能訪問任何一個鑰匙鏈項。在iOS裏,一個應用程序只能訪問自己的鑰匙鏈項。

Note: On iPhone, Keychain rights depend on the provisioning profile used to sign your application. Be sure to consistently use the same provisioning profile across different versions of your application.

注意:在iPhone中,鑰匙鏈依賴於 provisioning profile 文件來標識你的應用程序。確保應用程序在不同版本中一貫的使用同一個 provisioning profile 文件

In iOS,there is a single keychain accessible to applications. Although it stores the keychain items of all the applications on the system, an application can access only its own keychain items (with the possible exception of a keychain item for which the application that created it obtained a persistent reference).

在iOS裏,有一個單獨的鑰匙鏈供應用程序訪問。儘管他存儲了系統裏全部應用程序的鑰匙鏈項,一個應用程序只能並且僅能訪問它自己的鑰匙鏈項(包括因爲應用程序創建包含了一個持久的引用二引發的可能的鑰匙鏈項異常)

Structure of a Keychain
Each keychain can contain any number of keychain items. Each keychain item contains data plus a set of attributes. For a keychain item that needs protection, such as a password or private key (a string of bytes used to encrypt or decrypt data), the data is encrypted and protected by the keychain. For keychain items that do not need protection, such as certificates, the data is not encrypted.

鑰匙鏈結構
每一個鑰匙鏈可以包含任意數量的鑰匙鏈項。每個鑰匙鏈項包含數據加上一些屬性集。對一個鑰匙鏈項來說需要進行保護,比如像一個密碼或這個私有鍵(加密或者揭祕的二進制數據字符串),數據被鑰匙鏈加密和保護。對多個鑰匙鏈項來說不需要保護,比如像證書,它的數據是不加密的。

The iOS gives an application access to only its own keychain items.

在iOS中,僅給一個用程序訪問它自己的鑰匙項權限。

The iOS Keychain Services API uses a different paradigm. This API has a single function (SecItemAdd) for adding an item to a keychain.

在iOS鑰匙鏈服務API使用了一個不同的範式(相對於Mac OS X)。這個API有一個單獨的函數(SecItemAdd)來添加一個鑰匙鏈項。

In iOS, you call the SecItemCopyMatching function to find a keychain item owned by your application. In this case there’s only one keychain and the user is never prompted to unlock it.

在iOS中,你調用SecItemCopyMatching函數來查找你應用程序自己的鑰匙鏈項目。在這種情況下,僅有一個鑰匙鏈並且用戶不需要被提示來解鎖它(相對於Mac OS X)。

iOS鑰匙鏈服務搜索字典

在iOS,鑰匙鏈服務使用鍵值對字典方式來制定鑰匙鏈項的屬性,這樣你就能查找或者創建。

經典的搜索字典組成:

class key:用來指定要搜索的鑰匙鏈項的類型(比如,互聯網密碼 或者密碼密鑰)。

一個或多個鍵值對來指定匹配屬性數據(比如標籤或者創建日期)

一個或多個搜索鍵值對,用來指定值來精確搜索,比如發行證書或者郵件地址來匹配。

一個返回值鍵值對,來指定你想要的數據(比如。一個字典或者是一個偏好引用)。
什麼樣的屬性值被指定,取決於你要搜索的鑰匙鏈項的類型。舉例,如果你指定鍵位kSecClass的值爲kSecClassGenericPassword,然後你可以指定創建時間的值或這個修改時間的值,但是不能指定主題或發行者(這個被用於證書)。

舉例,如果你想執行一個對AppStore賬戶名爲’ImaUser’密碼不敏感情況的搜索,你可以在SecItemCopyMatching函數,使用上面表格中的鍵值對。

kSecReturnData鍵是函數返回鑰匙鏈項的數據,如果你想得到鍵值對的值,你需要使用kSecReturnAttributes返回類型鍵並且值爲kCFBooleanTrue.

2. iOS中使用keychain和userdefaults保存數據的對比



1. userdefault適合保存一些輕量級的數據,使用userdefault保存的數據加載的時候要快一些,數據以明文的形式保存在.plist文件中,不適合用來保存密碼信息。文件的位置是Library/Application Support/iPhone Simulator/模擬器版本/Applications/應用對應的數字/Library/Preference/.plist文件

2. keychain採用的是將數據加密之後再保存到本地的,這樣對數據而言有更高的安全性,適合保存密碼之類的數據。數據保存的目錄是Library/Application Support/iPhone Simulator/模擬器版本/Library/Keychains/

3. SSKeychain的使用



github地址: https://github.com/samsoffes/sskeychain

SSKeychain對apple安全框架API進行了簡單封裝,支持對存儲在鑰匙串中密碼、賬戶進行訪問,包括讀取、刪除和設置;

在工程中加入SSKeyChain

方法一: 手動添加
在工程中加入Security.framework框架。
SSKeychain.hSSKeychain.m加到項目文件夾。

方法二: 使用第三方管理工具
pod 'SSKeychain', '~> 1.3.1'

使用

SSKeyChain使用起來非常的簡單, 方法也不多

//獲取所有賬號
+ (NSArray *)allAccounts;

//獲取某個服務下的所有賬號
+ (NSArray *)accountsForService:(NSString *)serviceName;

//設置特定服務下的給定賬號的密碼
+ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account;

//獲取某個服務下的某個賬號的密碼
+ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account;

//刪除某個服務下的某個賬號的密碼
+ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account;

注意:

  1. 以上方法中的serviceNameaccount 參數應該是一致的這樣才能保證真確的操作, 建議使用宏定義 或者 static NSString *kServiceName = @"ServiceName";

  2. 如果你保存密碼失敗,處理方法:

NSError *error = nil;  
NSString *password = [SSKeychain passwordForService:@"自定義的服務器名" account:@"賬號" error:&error];  

if ([error code] == SSKeychainErrorNotFound) {  
    NSLog(@"該賬戶沒有儲存密碼"); 
    //you should do something more sophisticated 
}  

參考文檔:
1. https://github.com/samsoffes/sskeychain
2. http://www.ithao123.cn/content-2407927.html
3. https://developer.apple.com/library/ios/documentation/Security/Reference/keychainservices/index.html#//apple_ref/doc/constant_group/Keychain_Import_Export_Options
4. http://www.kanyinqing.com/read/it/other/445654.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章