Ios Keychain《二》的三种使用方法

21 篇文章 0 订阅

demo下载

上一篇介绍了Keychain的基本内容接下来介绍三种的使用

keychain的使用

这里总结keychain三个使用方法,分别是

  • 苹果官方的KeychainItemWrapper
  • 第三方封装SAMKeychain
  • 通过Security.framework框架使用

这三个方法我最推崇的是使用sskeychain这个封装的方案,更加简单方便,下载和使用地址在后面,现在开始说下每一个方法的使用

KeychainItemWrapper的使用

KeychainItemWrapper是苹果官方推出的,链接地址:点击进入官方文档,这个因为是官方推出的,所以很多人用,但是会有点坑,使用方案,首先去官方地址或者后面我的demo中,把KeychainItemWrapper.h和KeychainItemWrapper.m引入工程。

使用步骤
第一步:
把KeychainItemWrapper.h和KeychainItemWrapper.m引入工程
第二步:
把KeychainItemWrapper.m使用-fno-objc-arc这个关闭arc
如图所示:
在这里插入图片描述
第三步:

KeychainItemWrapper *warp = [[KeychainItemWrapper alloc]initWithIdentifier:identifier accessGroup:aGroup];
        [warp objectForKey:(id)kSecValueData];
        //必须
        [warp setObject:identifier forKey:(id)kSecAttrService];
        //必须
        [warp setObject:identifier forKey:(id)kSecAttrAccount];
        [warp setObject:object forKey:(id)kSecValueData];
        //权限
        [warp setObject:(id)kSecAttrAccessibleAlwaysThisDeviceOnly forKey:(id)kSecAttrAccessible];
#if TARGET_IPHONE_SIMULATOR
        // Note: 如果在模拟器中运行,则无法设置访问组。模拟器中运行的应用程序没有签名,因此没有访问组供它们检查。在模拟器中运行的所有应用程序都可以看到所有的密钥链项。如果需要测试共享访问组的应用程序,则需要在设备上安装这些应用程序。
#else
        if ([accessGroup length] > 0)
        {
            [warp setObject: accessGroup forKey:(id)kSecAttrAccessGroup];
        }
#endif

优缺点

  • 需禁用KeychainItemWrapper.h/.m文件的ARC,但现在流行ARC
  • keychain内部应该是根据kSecAttrService和kSecAttrAccount作为标识的,所以必须设置
  • 需要的参数少

SAMKeychain的使用方法

SAMKeychain是samsoffes大神封装的一个方法,不像KeychainItemWrapper需要设置太多的选项,所以很好用
github下载地址:https://github.com/soffes/SAMKeychain

使用步骤
第一步:
使用方法就是下载之后,把SSKeychain.h和SSKeychain.m文件拖入到自己的工程中,导入头文件即可

[SAMKeychain setPassword:password forService:serviceName account:account];

优缺点

  • 使用比较简单
  • 内部已经封好了service等内容不会崩溃
    区分NSString和NSData

Security.framework的使用
这个用到了系统库#import <Security/Security.h>
是用

Keychain的用法
首先导入Security.framework 。

Keychain的API提供以下几个函数来操作Keychain

  • SecItemAdd 添加一个keychain item
  • SecItemUpdate 修改一个keychain item
  • SecItemCopyMatching 搜索一个keychain item
  • SecItemDelete 删除一个keychain item
    也可以参考以下这段简单的代码来了解下Keychain API的用法。

优缺点

  • 比较繁琐
    安全性更高
- (NSMutableDictionary *)newSearchDictionary:(NSString *)identifier {
    NSMutableDictionary *searchDictionary = [[NSMutableDictionary alloc] init];
    //指定item的类型为GenericPassword
    [searchDictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];
    
    //类型为GenericPassword的信息必须提供以下两条属性作为unique identifier
    [searchDictionary setObject:encodedIdentifier forKey:(id)kSecAttrAccount];
    [searchDictionary setObject:encodedIdentifier forKey:(id)kSecAttrService];
    
    return searchDictionary;
}
- (NSData *)searchKeychainCopyMatching:(NSString *)identifier {
    NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier];
    
    //在搜索keychain item的时候必须提供下面的两条用于搜索的属性
    //只返回搜索到的第一条item,这个是搜索条件。
    [searchDictionary setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
    //返回item的kSecValueData 字段。也就是我们一般用于存放的密码,返回类型为NSData *类型
    [searchDictionary setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
   
  //我来解释下这里匹配出的是 找到一条符合ksecAttrAccount、类型为普通密码类型kSecClass,返回ksecValueData字段。
    NSData *result = nil;
    OSStatus status = SecItemCopyMatching((CFDictionaryRef)searchDictionary,
                                          (CFTypeRef *)&result);
    [searchDictionary release];
    return result;
}
- (BOOL)createKeychainValue:(NSString *)password forIdentifier:(NSString *)identifier {
    NSMutableDictionary *dictionary = [self newSearchDictionary:identifier];
    
  //非常值得注意的事kSecValueData字段只接受UTF8格式的 NSData *类型,否则addItem/updateItem就会crash,并且一定记得带上service和account字段
    NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
    [dictionary setObject:passwordData forKey:(id)kSecValueData];
    
    OSStatus status = SecItemAdd((CFDictionaryRef)dictionary, NULL);
    [dictionary release];
    if (status == errSecSuccess) {
        return YES;
    }
    return NO;
}
- (BOOL)updateKeychainValue:(NSString *)password forIdentifier:(NSString *)identifier {
    NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier];
    
    NSMutableDictionary *updateDictionary = [[NSMutableDictionary alloc] init];
    NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
    [updateDictionary setObject:passwordData forKey:(id)kSecValueData];
    
  //这里也有需要注意的地方,searchDictionary为搜索条件,updateDictionary为需要更新的字典。这两个字典中一定不能有相同的key,否则就会更新失败
    OSStatus status = SecItemUpdate((CFDictionaryRef)searchDictionary,
                                    (CFDictionaryRef)updateDictionary);
    
    [searchDictionary release];
    [updateDictionary release];
    
    if (status == errSecSuccess) {
        return YES;
    }
    return NO;
}
- (void)deleteKeychainValue:(NSString *)identifier {
    NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier];
    SecItemDelete((CFDictionaryRef)searchDictionary);
    [searchDictionary release];
}

使用keychain需要注意的问题
1.当我们不支持Keychain Access Group,并且没有entitlement文件时,keychain默认以bundle id为group。如果我们在版本更新的时候改变了bundle id,那么新版本就访问不了旧版本的keychain信息了。解决办法是从一开始我们就打开KeychainSharing,添加Keychain Access Group,并且指定每条keychain Item的group,私有的信息就指定app的bundle id为它的group。
2.代码内Access group名称一定要有AppIdentifierPrefix前缀。
Keychain是基于数据库存储,不允许添加重复的条目。所以每条item都必须指定对应的唯一标识符也就是那些主要的key,如果Key指定不正确,可能会出现添加后查找不到的问题。
3.kSecAttrSynchronizable也会作为主要的key之一。它的value值默认为No,如果之前添加的item此条属性为YES,在搜索,更新,删除的时候必须添加此条属性才能查找到之前添加的item。
Kechain item字典内添加自定义key时会出现参数不合法的错误。
ksecValueData必须为UTF8的NSData类型。
4.kSecClass中的主键值,不允许添加2个相同的值。否则会添加失败。 对应主要的key是一定要包含的,否则会写入失败。
5.更新函数SecItemUpdate ,第一个参数为搜索条件,第二个参数为需要更新的键值。两个不能有重复key,否则会失败。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值