iOS 钥匙串的基本使用

栏目: IOS · 发布时间: 5年前

内容简介:级别: ★☆☆☆☆标签:「钥匙串」「keychain」「iOS」作者: WYW

级别: ★☆☆☆☆

标签:「钥匙串」「keychain」「iOS」

作者: WYW

审校:QiShare团队

前言 :

项目中有时会需要存储敏感信息(如密码、密钥等),苹果官方提供了一种存储机制-- 钥匙串(keychain)

keychain是一种存储在 硬盘 上的 加密的数据库 。这个可能是卸载App后,keychain信息还在的原因。

keychain适合存储 较小的数据量不超过上千字节或上兆字节 )的内容。

笔者做了一个关于keychain的 增、删、改、查 的Demo(QiKeychain),给大家介绍下keychain的基本使用。

下图(确保keychain中用户的信息安全)有利于我们直观了解keychain。

iOS 钥匙串的基本使用

Demo(QiKeychain)解读:

笔者用Demo(QiKeychain)做了4件事。

  • 增加:存储用户名、密码到keychain;
  • 查询:根据用户名从keychain中查询密码;
  • 删除:从keychain中删除用户名、密码等相应信息;
  • 修改:修改keychain中的用户名对应的密码;

Demo(QiKeychain)对keychain的操作效果如下:

  • 存储用户名 “QiShare”,密码:1234;
  • 查询用户名为“QiShare”的密码,显示密码为:1234;
  • 修改用户名“QiShare”的密码为“123456”;
  • 查询“QiShare”的密码,显示为“123456”;
  • 把“QiShare”从keychain中删除。
iOS 钥匙串的基本使用

keychain基本使用API

keychain有四个常用的API,用于增、删、改、查keychain中的数据。

keychain中的数据子项是以item的形式存在的。

举个例子:就存储用户名、密码的情景来说,每个item包含存储的用户名和密码及其他属性信息,keychain中包含多个用户名和密码的item。

下图(把数据和属性存储到keychain中)利于我们理解存储过程

iOS 钥匙串的基本使用

SecItemAdd:添加一个item或多个items到keychain

OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef * __nullable CF_RETURNS_RETAINED result)
    API_AVAILABLE(macos(10.6), ios(2.0));
复制代码

存储关键代码:

NSDictionary *saveSecItems = @{(id)kSecClass: (id)kSecClassGenericPassword,
                               (id)kSecAttrService: service,
                               (id)kSecAttrAccount: account,
                               (id)kSecValueData: passwordData
                               };
    OSStatus saveStatus = SecItemAdd((CFDictionaryRef)saveSecItems, NULL);
复制代码

SecItemCopyMatching:返回匹配搜索查询的一个item或多个items

OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef * __nullable CF_RETURNS_RETAINED result)
    API_AVAILABLE(macos(10.6), ios(2.0));
复制代码

查询关键代码:

NSDictionary *matchSecItems = @{
                                    (id)kSecClass: (id)kSecClassGenericPassword,
                                    (id)kSecAttrService: service,
                                    (id)kSecAttrAccount: account,
                                    (id)kSecMatchLimit: (id)kSecMatchLimitOne,
                                    (id)kSecReturnData: @(YES)
                                    };
  CFTypeRef dataRef = nil;
  OSStatus errorCode = SecItemCopyMatching((CFDictionaryRef)matchSecItems, (CFTypeRef *)&dataRef);
复制代码

SecItemUpdate:修改匹配搜索查询的一个item或多个items

OSStatus SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate)
    API_AVAILABLE(macos(10.6), ios(2.0));
复制代码

注意:更新代码这部分,笔者开始的时候遇到一些问题,还要多谢组内成员,尤其是昆哥的指教。

SecItemUpdate接收了2个参数,query和attributesToUpdate。

第一个参数query用于查询到相应的item, 第二个参数attributesToUpdate用于传入要更新的信息。

笔者曾错误地给第二个参数attributesToUpdate传入过(id)kSecClass: (id)kSecClassGenericPassword要更改的内容。

结果报错为:

errSecNoSuchAttr = -25303, /* The specified attribute does not exist. */

更新关键代码:

NSDictionary *queryItems = @{(id)kSecClass: (id)kSecClassGenericPassword,
                               (id)kSecAttrService: service,
                               (id)kSecAttrAccount: account
                               };
    NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary *updatedItems = @{
                                   (id)kSecValueData: passwordData,
      };
    OSStatus updateStatus = SecItemUpdate((CFDictionaryRef)queryItems, (CFDictionaryRef)updatedItems);
复制代码

SecItemDelete:删除匹配搜索查询的一个item或多个items

OSStatus SecItemDelete(CFDictionaryRef query)
    API_AVAILABLE(macos(10.6), ios(2.0));
复制代码

删除关键代码:

NSDictionary *deleteSecItems = @{
                                    (id)kSecClass: (id)kSecClassGenericPassword,
                                    (id)kSecAttrService: service,
                                    (id)kSecAttrAccount: account
                                    };
    OSStatus errorCode = SecItemDelete((CFDictionaryRef)deleteSecItems);
复制代码

显然keychain的 增删改查 相关的API都需要设置相应的 属性字典 (分别代指上述的saveSecItems 、matchSecItems 、queryItems 、updatedItems 、deleteSecItems)

  • 属性字典的key、value常用的有:(这部分内容读者也可直接看文档)
  • (id)kSecClass: (id)kSecClassGenericPassword kSecClass表示item的class (id)kSecClass的值表明一个通用的密码item笔者一般都传入kSecClassGenericPassword
  • (id)kSecAttrService: service kSecAttrService的value用于表明item的service
  • (id)kSecAttrAccount: account (id)kSecAttrAccoun的值表明item的帐户名
  • (id)kSecValueData: passwordData (id)kSecValueData表示item的数据
  • (id)kSecMatchLimit: (id)kSecMatchLimitOne, (id)kSecMatchLimit 有2个值(id)kSecMatchLimitOne、和(id)kSecMatchLimitAll kSecMatchLimitOne:表示只匹配第一个符合条件的item kSecMatchLimitAll:表示匹配不限数量的items
  • (id)kSecReturnData: @(YES) (id)kSecReturnData的值是一个Boolean类型的值用于确定是否返回item data
  • kSecClass的值表示item的class kSecClass的值表明一个通用的密码item笔者一般都传入的kSecClassGenericPassword
  • kSecClass的值表示item的class kSecClass的值表明一个通用的密码item笔者一般都传入的kSecClassGenericPassword

Demo(QiKeychain)相关代码

在Demo(QiKeychain)中,笔者对keychain相关使用的API进行了封装。获取 Demo(QiKeychain) GitHub地址: QiKeychain

注意: 笔者后来封装的代码,修改了保存操作的逻辑。

修改内容为: 在保存用户名密码的时候

-> 先在keychain中 查询 用户名是否存在

-> 若存在,就进行 更新 操作;

-> 若不存在就进行 保存 操作。

相应示意图(使用钥匙串存储网络密码)如下:

iOS 钥匙串的基本使用

以上所述就是小编给大家介绍的《iOS 钥匙串的基本使用》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

2小时品牌素养

2小时品牌素养

邓德隆 / 2009-1 / 38.00元

《2小时品牌素养(第2版)》第一次系统发布有关中国企业的品牌竞争力分析报告,揭示了中国一流企业在品牌战略上面临的深重危机,提出了定位突围之道和实践方法。全书分上下两篇,上篇详细分析了定位的原理,给出定位的三种方法,并特别为中国企业走向世界指出了三条出路;下篇以王老吉品牌战略历程为例,细致论述了一个品牌打造的完整过程,并就品牌实践中的许多关键问题进行了阐述和研讨。作为兼顾理论和实践的第2版,《2小时......一起来看看 《2小时品牌素养》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

MD5 加密
MD5 加密

MD5 加密工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换