iOS簡單使用keychain存儲密碼


2016.12.22最新更新
最近一直有朋友說不知道怎么用,特來更新了 PDKeyChain,添加了注釋,有問題可以提 issue 歡迎討論。


2016.8.23最新更新
最近一直有朋友問源碼,整理了一下發在這里


2016.3.23最新更新
近期項目中又用到keychain,于是回頭翻了翻以前寫的代碼,感覺寫的/(ㄒoㄒ)/~~
設計不科學,命名不規范,怎么看怎么別扭,那就重寫吧~


Tips:在實習過程中,有次讓我實現一個app七天免登陸功能。當時沒細想,直接就用NSUserDefaults給做的,用NSDate判斷時間,取七天的間隔判斷登陸狀態。直到現在了解了keychain,才知道用NSUserDefaults是非常不安全的。通常情況下,可以用NSUserDefaults存儲數據信息,但是對于一些私密信息,比如賬號、密碼等等,就需要使用更為安全的keychain了。而Keychain的信息是存在于每個應用(app)的沙盒之外的,所以keychain里保存的信息不會因App被刪除而丟失,在用戶重新安裝App后依然有效,數據還在。

KeyChain

話不多說,咱們直接來看怎么快速集成keychain。

  1. 自定義一個類,取名XXXKeyChain,如下:
#import <Foundation/Foundation.h>
#import <Security/Security.h>
#define KEY_PASSWORD  @"com.rry.app.password"
#define KEY_USERNAME_PASSWORD  @"com.rry.app.usernamepassword"
@interface RRYKeyChain : NSObject
+ (void)save:(NSString *)service data:(id)data;
+ (id)load:(NSString *)service;
+ (void)delete:(NSString *)service;
@end

以上代碼自定義了三個方法,存、取、刪。并且定義了幾個字符串用來做key。當然,想使用keychain請不要忘記引入Security包,引入文件 #import <Security/Security.h>。

  1. 再來看.m文件的具體實現
#import "RRYKeyChain.h"

@implementation RRYKeyChain
+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
    return [NSMutableDictionary dictionaryWithObjectsAndKeys:
            (id)kSecClassGenericPassword,(id)kSecClass,
            service, (id)kSecAttrService,
            service, (id)kSecAttrAccount,
            (id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible,
            nil];
}

+ (void)save:(NSString *)service data:(id)data {
    //Get search dictionary
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    //Delete old item before add new item
    SecItemDelete((CFDictionaryRef)keychainQuery);
    //Add new object to search dictionary(Attention:the data format)
    [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
    //Add item to keychain with the search dictionary
    SecItemAdd((CFDictionaryRef)keychainQuery, NULL);
}

+ (id)load:(NSString *)service {
    id ret = nil;
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    //Configure the search setting
    //Since in our simple case we are expecting only a single attribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue
    [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: %@", service, e);
        } @finally {
        }
    }
    if (keyData)
        CFRelease(keyData);
    return ret;
}

+ (void)delete:(NSString *)service {
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    SecItemDelete((CFDictionaryRef)keychainQuery);
}

然后就是存,其中mmm是要存的密碼字符串。

NSMutableDictionary *usernamepasswordKVPairs = [NSMutableDictionary dictionary];
[usernamepasswordKVPairs setObject:mmm forKey:KEY_PASSWORD];
[RRYKeyChain save:KEY_USERNAME_PASSWORD data:usernamepasswordKVPairs];

NSMutableDictionary *usernamepasswordKVPairs = (NSMutableDictionary *)[RRYKeyChain load:KEY_USERNAME_PASSWORD];

NSLog(@"%@",[usernamepasswordKVPairs objectForKey:KEY_PASSWORD]);

[RRYKeyChain delete:KEY_USERNAME_PASSWORD];

這樣一個簡單的使用keychain快速存儲密碼的功能就做好了。


2016.3.23最新更新

話不多說,直接上代碼,首先是.h

#import <Foundation/Foundation.h>
#import <Security/Security.h>

@interface RHKeyChain : NSObject

+ (void)rhKeyChainSave:(NSString *)service;

+ (NSString *)rhKeyChainLoad;

+ (void)rhKeyChainDelete:(NSString *)service;

@end

只對外提供三個方法,存、取、刪,實現放在內部,再是.m

static NSString * const kRHDictionaryKey = @"com.xxxx.dictionaryKey";
static NSString * const kRHKeyChainKey = @"com.xxxx.keychainKey";

+ (void)rhKeyChainSave:(NSString *)service {
    NSMutableDictionary *tempDic = [NSMutableDictionary dictionary];
    [tempDic setObject:service forKey:kRHDictionaryKey];
    [self save:kRHKeyChainKey data:tempDic];
}

+ (NSString *)rhKeyChainLoad{
    NSMutableDictionary *tempDic = (NSMutableDictionary *)[self load:kRHKeyChainKey];
    return [tempDic objectForKey:kRHDictionaryKey];
}

+ (void)rhKeyChainDelete{
    [self delete:kRHKeyChainKey];
}

三個方法的實現。


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,846評論 25 708
  • keychain app官方鏈接 重要的事情說三遍 使用keychain group的時候,測試一定要使用真機! ...
    Rxiaobing閱讀 3,239評論 1 5
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,188評論 4 61
  • 余額寶最近又有新動作啦!余額寶基金管理人的天弘基金,近日已發布公告稱:自8月14日零點起,個人持有余額寶的最高額度...
    好車貸理財君閱讀 284評論 0 1
  • 新來的同事,第一眼看過去就有一種很熟悉的感覺。讓我下意識的對其很親近,各種能夠幫到的事情不留余力的提供。今天猛然想...
    學道之人閱讀 311評論 0 0