SSKeychain
Keychain 使用? ---為了實(shí)用最大化我覺(jué)得我應(yīng)該直接先說(shuō)使用!
當(dāng)然是使用第三方庫(kù)啦:sskeychain 3000+星星的庫(kù)不開(kāi)玩笑。github地址:https://github.com/soffes/sskeychain
導(dǎo)入完之后首先,編譯一下有無(wú)錯(cuò)。
如果是自己手動(dòng)導(dǎo)入:
1.把SSKeychain.h SSKeychain.m SSKeychainQuery.h SSKeychainQuery.m 復(fù)制到工程
2.添加Security.framework 怎么添加?點(diǎn)一下那個(gè)+?
?
3.SSKeychain.h有錯(cuò)?把SSKeychain.h 中的#import <SSKeychain/SSKeychainQuery.h> 換成?#import <Foundation/Foundation.h>?#import "SSKeychainQuery.h" 吧。
還有錯(cuò)?作為小白我的也不知道了,發(fā)我郵件一起討論吧。
?
?
接下來(lái)演示4個(gè)過(guò)程
基本說(shuō)明:儲(chǔ)存的數(shù)據(jù)有三個(gè) 1.服務(wù)名(這個(gè)方便對(duì)賬號(hào)密碼進(jìn)行分類)2.賬號(hào)3.密碼 而這三個(gè)數(shù)據(jù)都是NSString (如果要存其他類型呢,請(qǐng)看后面吧)
所用到的API :
添加和更新都用這個(gè): + (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.添加一條鑰匙 ? ?(這個(gè)鑰匙的信息 由 服務(wù)名+賬號(hào)+密碼 組成)
記得添加頭文件
#import "SSKeychain.h"
#import "SSKeychainQuery.h"
?
//先定義一下要用的東東
? ??NSString *serviceName= @"com.keychaintest.data";
? ? NSString *account = @"m4abcd";
? ? NSString *password = @"12345678";
//加入鑰匙串!
? ? if ([SSKeychain setPassword:password forService:serviceName account:account]) {
? ? ? ? NSLog(@"success !");
? ? }
說(shuō)明:就是這么簡(jiǎn)單咯。
2.查詢
1.查詢某service 下 count 的密碼并且打印出來(lái):
NSLog(@"%@",[SSKeychain passwordForService:serviceName account:account]);
2.查詢service下所有鑰匙:
? ? ?NSArray *keys = [SSKeychain accountsForService:serviceName];
這是我的輸出:
2016-03-04 15:08:43.785 keychaintest[31342:4403403] (
? ? ? ? {
? ? ? ? acct = m4abcd;
? ? ? ? agrp = test;
? ? ? ? cdat = "2016-03-03 07:10:58 +0000";
? ? ? ? mdat = "2016-03-04 07:08:43 +0000";
? ? ? ? pdmn = ak;
? ? ? ? svce = "com.keychaintest.data";
? ? ? ? sync = 0;
? ? ? ? tomb = 0;
? ? }
)
說(shuō)明:返回的結(jié)果為數(shù)組,數(shù)組成員就是我們查詢的鑰匙,這里只有一個(gè)鑰匙,而鑰匙信息以字典的形式構(gòu)建的,鍵acct 就是count,鍵svce 就是serviceName。密碼在哪里?用方法1去取吧騷年!
3.查詢本appkeychain的所有鑰匙
NSArray?*keys =?[SSKeychain allAccounts];?
3.更新
? ? if([SSKeychain setPassword:@"321321" forService:serviceName account:account]){
NSLog(@"set success!");
}
4.刪除
? if([SSKeychain?deletePasswordForService:serviceName account:account]){
NSLog(@"delete success!");
}
?說(shuō)明:刪除就是把這一條鑰匙刪除哦,不是只刪除密碼!
另外的說(shuō)明:如果你的password 是NSData?
查詢: + (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account;
設(shè)置or更新:+ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account;
?
下面開(kāi)始淺淺的理解還有對(duì)蘋果API進(jìn)行一點(diǎn)點(diǎn)說(shuō)明吧
1.Keychain 是什么?
keychain 就是放鑰匙柜子!就是蘋果提供給我們的一個(gè)保險(xiǎn)柜。
這篇文章僅針對(duì)iOS。
在iOS中每個(gè)APP 都有屬于自己的Keychain,最常用就是保存用戶的賬戶和密碼,就是記住密碼,放在這里很安全(蘋果負(fù)責(zé)幫我們加密再存起來(lái),如果出了問(wèn)題怪他咯!),假如用NSUserDefault 保存這些秘密數(shù)據(jù),生成的plist文件(就放在那個(gè)Library/Preferences 下)容易被拿到,而且還要自己做加密。
特性:1.當(dāng)app刪除了,又再次重新安裝,這個(gè)保險(xiǎn)柜里的信息還存在哦。 所以當(dāng)你的某女同學(xué)登了APP并保存了密碼,你重裝了APP,如果不刪除記錄,你女票還是可以發(fā)現(xiàn)的。
2.安全!作為小白的我并不知道它實(shí)際上是存在哪里的。
2.Keychain 組成?
1.組成部分由 ?{N個(gè)標(biāo)簽(屬性) + 一個(gè)重要數(shù)據(jù)} 組成!
2.結(jié)構(gòu)可以看成是一個(gè)字典的形式大概是這樣的: @{@"屬性key1":@"屬性值1",@"屬性keyN":@"屬性值N",@"valueData":@數(shù)據(jù)}?
3.內(nèi)容說(shuō)明:
一個(gè)重要數(shù)據(jù):就是密碼password!
N個(gè)標(biāo)簽:也是屬性,都是用來(lái)表明這條鑰匙的,如我們的serviceName ,account 都是屬性,他們對(duì)應(yīng)的鍵為?kSecAttrAccount 和?kSecAttrAccount,還有系統(tǒng)給我們加的創(chuàng)建時(shí)間,修改時(shí)間等還有l(wèi)abel,type,port,你自己打開(kāi)文件進(jìn)去看看吧,這些標(biāo)簽的任務(wù)就是來(lái)表明這條鑰匙是獨(dú)一無(wú)二的。?
3.原始API操作
先來(lái)看看幾個(gè)API
添加鑰匙: OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef * __nullable CF_RETURNS_RETAINED result)
查詢密碼與查詢標(biāo)簽: ??OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef * __nullable CF_RETURNS_RETAINED result)
更新鑰匙信息: ? ? ? ? ? OSStatus SecItemUpdate(CFDictionaryRef query,?CFDictionaryRef attributesToUpdate)
刪除鑰匙: OSStatus SecItemDelete(CFDictionaryRef query)
先說(shuō)明一下 這些API的關(guān)鍵在于1.是理解和配置好這個(gè)操作字典 2.注意返回的OSStatus 狀態(tài)?3.CF對(duì)象與OC 之間的bridge
1.先來(lái)一發(fā)查找 ?
過(guò)程:
1.(關(guān)鍵)先配置一個(gè)操作字典內(nèi)容有:
kSecAttrService(屬性),kSecAttrAccount(屬性) 這些屬性or標(biāo)簽是查找的依據(jù)
kSecReturnData(值為@YES 表明返回類型為data),kSecClass(值為kSecClassGenericPassword 表示重要數(shù)據(jù)為“一般密碼”類型) 這些限制條件是返回結(jié)果類型的依據(jù)
2.然后用查找的API 得到查找狀態(tài)和返回?cái)?shù)據(jù)(密碼)
3.最后如果狀態(tài)成功那么將數(shù)據(jù)(密碼)轉(zhuǎn)換成string 返回
//用原生的API 實(shí)現(xiàn)查詢密碼
- (NSString *)passwordForService:(nonnull NSString *)service account:(nonnull NSString *)account{
//生成一個(gè)查詢用的 可變字典
? ? NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:4];
? ? [dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; //表明為一般密碼可能是證書或者其他東西
? ? [dict setObject:service forKey:(__bridge id)kSecAttrService]; ? ?//輸入service
? ? [dict setObject:account forKey:(__bridge id)kSecAttrAccount]; ?//輸入account
? ? [dict setObject:@YES forKey:(__bridge id)kSecReturnData]; ? ? //返回Data
//查詢 ? ?
? ? OSStatus status = -1;
? ? CFTypeRef result = NULL;
? ? status = SecItemCopyMatching((__bridge CFDictionaryRef)dict,&result);//核心API?查找是否匹配?和返回密碼!
? ? if (status != errSecSuccess) { //判斷狀態(tài)
? ? ? ? return nil;
? ? }
//返回?cái)?shù)據(jù)
? ? NSString *password = [[NSString alloc] initWithData:(__bridge_transfer NSData *)result encoding:NSUTF8StringEncoding];//轉(zhuǎn)換成string
? ? return password;
}
說(shuō)明:其實(shí)關(guān)鍵就在于這個(gè)操作字典的配置上!
2.添加&更新
說(shuō)明:當(dāng)添加的時(shí)候我們一般需要判斷一下當(dāng)前鑰匙串里面是否已經(jīng)存在我們要添加的鑰匙。如果已經(jīng)存在我們就更新好了,不存在再添加,所以這兩個(gè)操作一般寫成一個(gè)函數(shù)搞定吧。
過(guò)程關(guān)鍵:1.檢查是否已經(jīng)存在 構(gòu)建的查詢用的操作字典:kSecAttrService,kSecAttrAccount,kSecClass(標(biāo)明存儲(chǔ)的數(shù)據(jù)是什么類型,值為kSecClassGenericPassword 就代表一般的密碼)
2.添加用的操作字典: kSecAttrService,kSecAttrAccount,kSecClass,kSecValueData
3.更新用的操作字典1(用于定位需要更改的鑰匙):kSecAttrService,kSecAttrAccount,kSecClass?
操作字典2(新信息)kSecAttrService,kSecAttrAccount,kSecClass ,kSecValueData
?
//用原生的API 添加一條鑰匙
-(BOOL)addItemWithService:(NSString *)service account:(NSString *)account password:(NSString *)password{
//先查查是否已經(jīng)存在
//構(gòu)造一個(gè)操作字典用于查詢
? ? NSMutableDictionary *searchDict = [[NSMutableDictionary alloc]initWithCapacity:4];
? ? [searchDict setObject:service forKey:(__bridge id)kSecAttrService]; ? ? ? ? ? ? ? ? ? ? ? ? //標(biāo)簽service
? ? [searchDict setObject:account forKey:(__bridge id)kSecAttrAccount]; ? ? ? ? ? ? ? ? ? ? ? ? //標(biāo)簽account
? ? [searchDict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];//表明存儲(chǔ)的是一個(gè)密碼
? ??
? ? OSStatus status = -1;
? ? CFTypeRef result =NULL;
? ? status = SecItemCopyMatching((__bridge CFDictionaryRef)searchDict, &result);
? ? if (status == errSecItemNotFound) {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //沒(méi)有找到則添加
? ? ? ? NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];? ? //把password 轉(zhuǎn)換為 NSData
? ? ? ? [searchDict setObject:passwordData forKey:(__bridge id)kSecValueData]; ? ? ? //添加密碼? ? ??
? ? ? ? status = SecItemAdd((__bridge CFDictionaryRef)searchDict, NULL); ? ? ? ? ? ? //!!!!!關(guān)鍵的添加API
? ? }else if (status == errSecSuccess){? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //成功找到,說(shuō)明鑰匙已經(jīng)存在則進(jìn)行更新
? ? ? ? NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];? ? //把password 轉(zhuǎn)換為 NSData
? ? ? ? NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithDictionary:searchDict];
? ? ? ? [dict setObject:passwordData forKey:(__bridge id)kSecValueData]; ? ? ? ? ? ? //添加密碼? ? ?
? ? ? ? status = SecItemUpdate((__bridge CFDictionaryRef)searchDict, (__bridge CFDictionaryRef)dict);//!!!!關(guān)鍵的更新API
? ? }
? ? return (status == errSecSuccess);
}
?
?
?
轉(zhuǎn)載:http://www.cnblogs.com/m4abcd/p/5242254.html
轉(zhuǎn)載于:https://www.cnblogs.com/sunjianfei/p/6560309.html
總結(jié)
以上是生活随笔為你收集整理的SSKeychain的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 1-13句子逆序
- 下一篇: gulp 实现sass自动化 ,监听同步