计算机网络技术电商网站建设与运营,wordpress文章添加目录,网站建设吗,推荐一个免费网站Keychain 使用? ---为了实用最大化我觉得我应该直接先说使用#xff01; 当然是使用第三方库啦#xff1a;sskeychain 3000星星的库不开玩笑。github地址#xff1a;https://github.com/soffes/sskeychain 导入完之后首先#xff0c;编译一下有无错。 如果是自己手动导入 当然是使用第三方库啦sskeychain 3000星星的库不开玩笑。github地址https://github.com/soffes/sskeychain 导入完之后首先编译一下有无错。 如果是自己手动导入 1.把SSKeychain.h SSKeychain.m SSKeychainQuery.h SSKeychainQuery.m 复制到工程 2.添加Security.framework 怎么添加点一下那个 3.SSKeychain.h有错把SSKeychain.h 中的#import SSKeychain/SSKeychainQuery.h 换成 #import Foundation/Foundation.h #import SSKeychainQuery.h 吧。 还有错作为小白我的也不知道了发我邮件一起讨论吧。 接下来演示4个过程 基本说明储存的数据有三个 1.服务名这个方便对账号密码进行分类2.账号3.密码 而这三个数据都是NSString (如果要存其他类型呢请看后面吧) 所用到的API : 添加和更新都用这个 (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.添加一条钥匙 这个钥匙的信息 由 服务名账号密码 组成 记得添加头文件 #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 !); } 说明就是这么简单咯。 2.查询 1.查询某service 下 count 的密码并且打印出来 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; } ) 说明:返回的结果为数组数组成员就是我们查询的钥匙这里只有一个钥匙而钥匙信息以字典的形式构建的键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!); } 说明删除就是把这一条钥匙删除哦不是只删除密码 另外的说明如果你的password 是NSData 查询 (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account; 设置or更新 (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account; 下面开始浅浅的理解还有对苹果API进行一点点说明吧 1.Keychain 是什么? keychain 就是放钥匙柜子就是苹果提供给我们的一个保险柜。 这篇文章仅针对iOS。 在iOS中每个APP 都有属于自己的Keychain最常用就是保存用户的账户和密码就是记住密码放在这里很安全(苹果负责帮我们加密再存起来如果出了问题怪他咯),假如用NSUserDefault 保存这些秘密数据生成的plist文件(就放在那个Library/Preferences 下)容易被拿到,而且还要自己做加密。 特性1.当app删除了,又再次重新安装,这个保险柜里的信息还存在哦。 所以当你的某女同学登了APP并保存了密码你重装了APP如果不删除记录你女票还是可以发现的。 2.安全作为小白的我并不知道它实际上是存在哪里的。 2.Keychain 组成? 1.组成部分由 {N个标签(属性) 一个重要数据} 组成 2.结构可以看成是一个字典的形式大概是这样的 {属性key1:属性值1属性keyN:属性值NvalueData:数据} 3.内容说明 一个重要数据就是密码password! N个标签也是属性都是用来表明这条钥匙的如我们的serviceName account 都是属性,他们对应的键为 kSecAttrAccount 和 kSecAttrAccount,还有系统给我们加的创建时间修改时间等还有label,type,port,你自己打开文件进去看看吧,这些标签的任务就是来表明这条钥匙是独一无二的。 3.原始API操作 先来看看几个API 添加钥匙 OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef * __nullable CF_RETURNS_RETAINED result) 查询密码与查询标签 OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef * __nullable CF_RETURNS_RETAINED result) 更新钥匙信息 OSStatus SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate) 删除钥匙 OSStatus SecItemDelete(CFDictionaryRef query) 先说明一下 这些API的关键在于1.是理解和配置好这个操作字典 2.注意返回的OSStatus 状态 3.CF对象与OC 之间的bridge 1.先来一发查找 过程 1.(关键)先配置一个操作字典内容有: kSecAttrService(属性),kSecAttrAccount(属性) 这些属性or标签是查找的依据 kSecReturnData(值为YES 表明返回类型为data),kSecClass(值为kSecClassGenericPassword 表示重要数据为“一般密码”类型) 这些限制条件是返回结果类型的依据 2.然后用查找的API 得到查找状态和返回数据密码 3.最后如果状态成功那么将数据密码转换成string 返回 //用原生的API 实现查询密码 - (NSString *)passwordForService:(nonnull NSString *)service account:(nonnull NSString *)account{ //生成一个查询用的 可变字典 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) { //判断状态 return nil; } //返回数据 NSString *password [[NSString alloc] initWithData:(__bridge_transfer NSData *)result encoding:NSUTF8StringEncoding];//转换成string return password; } 说明:其实关键就在于这个操作字典的配置上 2.添加更新 说明当添加的时候我们一般需要判断一下当前钥匙串里面是否已经存在我们要添加的钥匙。如果已经存在我们就更新好了不存在再添加所以这两个操作一般写成一个函数搞定吧。 过程关键1.检查是否已经存在 构建的查询用的操作字典kSecAttrServicekSecAttrAccountkSecClass标明存储的数据是什么类型值为kSecClassGenericPassword 就代表一般的密码 2.添加用的操作字典 kSecAttrServicekSecAttrAccountkSecClasskSecValueData 3.更新用的操作字典1用于定位需要更改的钥匙kSecAttrServicekSecAttrAccountkSecClass 操作字典2新信息kSecAttrServicekSecAttrAccountkSecClass ,kSecValueData //用原生的API 添加一条钥匙 -(BOOL)addItemWithService:(NSString *)service account:(NSString *)account password:(NSString *)password{ //先查查是否已经存在 //构造一个操作字典用于查询 NSMutableDictionary *searchDict [[NSMutableDictionary alloc]initWithCapacity:4]; [searchDict setObject:service forKey:(__bridge id)kSecAttrService]; //标签service [searchDict setObject:account forKey:(__bridge id)kSecAttrAccount]; //标签account [searchDict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];//表明存储的是一个密码 OSStatus status -1; CFTypeRef result NULL; status SecItemCopyMatching((__bridge CFDictionaryRef)searchDict, result); if (status errSecItemNotFound) { //没有找到则添加 NSData *passwordData [password dataUsingEncoding:NSUTF8StringEncoding]; //把password 转换为 NSData [searchDict setObject:passwordData forKey:(__bridge id)kSecValueData]; //添加密码 status SecItemAdd((__bridge CFDictionaryRef)searchDict, NULL); //!!!!!关键的添加API }else if (status errSecSuccess){ //成功找到说明钥匙已经存在则进行更新 NSData *passwordData [password dataUsingEncoding:NSUTF8StringEncoding]; //把password 转换为 NSData NSMutableDictionary *dict [[NSMutableDictionary alloc] initWithDictionary:searchDict]; [dict setObject:passwordData forKey:(__bridge id)kSecValueData]; //添加密码 status SecItemUpdate((__bridge CFDictionaryRef)searchDict, (__bridge CFDictionaryRef)dict);//!!!!关键的更新API } return (status errSecSuccess); } 转载http://www.cnblogs.com/m4abcd/p/5242254.html转载于:https://www.cnblogs.com/sunjianfei/p/6560309.html