iOS简单使用keychain存储密码

作者: 大慈大悲大熊猫 | 来源:发表于2015-04-07 10:19 被阅读26240次

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];
}

三个方法的实现。


相关文章

  • iOS简单使用keychain存储密码

    2016.12.22最新更新最近一直有朋友说不知道怎么用,特来更新了 PDKeyChain,添加了注释,有问题可以...

  • IOS使用 SFHFKeychainUtils 在 iOS ke

    为什么使用Keychain存储用户敏感信息 : iOS的keychain服务提供了一种安全的保存私密信息(密码,序...

  • SFHFKeychainUtils

    使用Keychain存储用户敏感信息 iOS的keychain服务提供了一种安全的保存私密信息(密码,序列号,证书...

  • 数据安全性-存储敏感的用户数据

    使用keychain来存储,也就是钥匙串,使用keychain需要导入Security框架 iOS的keychai...

  • 你会如何存储用户的一些敏感信息,如登录的token

    原文:iOS面试题大全 使用keychain来存储,也就是钥匙串,使用keychain需要导入Security框架...

  • Keychain Sharing

    1、前言 在iOS开发中,我们或多或少会使用Keychain服务来存储用户的账号密码、证书或其他重要的信息。 根据...

  • 2021-08-23

    iOS swift 钥匙串的Keychain 的详细使用 Keychain (密码管理系统) 数据并不存放在A...

  • Keychain与NSUserDefaults

    NSUserDefaults 简介,使用 NSUserDefaults 存储自定义对象iOS keyChain 研...

  • iOS Keychain总结

    概要 iOS中一般用Keychain存储密码、私钥等需要加密的数据。参考apple 官网介绍 使用方法 先总的说下...

  • 用keychain存储密码

    1.存本地不安全; 2.根据获取的token;来保持登录; 3.用keychain存储密码 iOS开发

网友评论

  • inoryshu:你这只能保存一个字符串?
  • 陌上北辰:我存进去了,但是取出来的是空,知道什么原因么
  • 王大吉Rock:问下你的7天免登陆 那是怎么设计的
    大慈大悲大熊猫:这个当时是把密码存在 keychain 里来做的。不严谨也不安全,建议还是配合服务端用 token 来做,具体的可以看下我这篇笔记:https://github.com/v2panda/PDSnippets/blob/master/PDSnippets/App/App%E7%AD%BE%E5%90%8D%E6%9C%BA%E5%88%B6.md
  • 18912bdd1fd6:复制粘贴很好玩?原文在这吧-》https://www.lvtao.net/ios/ios-keychain.html
    18912bdd1fd6:@菜刀切苹果 http://blog.csdn.net/cloudox_/article/details/48248651,这个是正确的,另外需要在Capabilities中将KeychainSharing打开
  • RickMao:目前这个好像不能使用了
    18912bdd1fd6:@RickMao http://blog.csdn.net/cloudox_/article/details/48248651,这个是正确的,另外需要在Capabilities中将KeychainSharing打开
    大慈大悲大熊猫:@RickMao 更新了项目,添加了注释,还有问题欢迎讨论。
  • 010377b0bae1:亲,我下载了你的demo 运行出来显示存成功了, 但是我第二次运行取出来是null 啊 怎么回事啊
    大慈大悲大熊猫:@小范520 更新了项目,添加了注释,还有问题欢迎讨论。
  • RickMao:请教一下,既然数据没有存储到app中,那数据存储到什么地方了呢?
    还有Pasteboard和keychain有什么区别呀!
  • i赵磊:我使用你的工具怎么存储账号和密码?
    为什么只传进入一个参数?

  • 56d35fdf1a2a:我之前运行过 用来存储用户名 后来改了一下两个宏(key)的值 就不能用了 改回来也无效 应该怎么解决呢
  • 菜鸟中的战斗鸡:额,我复制的你的代码,运行完关掉,卸载app后再运行,得到的value和之前存进去的不一样 :sweat:
    大慈大悲大熊猫:@菜鸟中的战斗机 见Demo:https://github.com/v2panda/PDKeyChain
  • 菜鸟中的战斗鸡:系统reset会丢失钥匙串么?
    大慈大悲大熊猫:@菜鸟中的战斗机 会的
    大慈大悲大熊猫:@菜鸟中的战斗机 会的
  • 61cb51a42b88:我都是拷贝的代码,但是nslog打印出来就是null,为什么?
    18912bdd1fd6:@最不想起名字 http://blog.csdn.net/cloudox_/article/details/48248651,这个是正确的,另外需要在Capabilities中将KeychainSharing打开
    大慈大悲大熊猫:@最不想起名字 见Demo:https://github.com/v2panda/PDKeyChain
  • 超_iOS:你这两个宏有什么特殊含义吗
    18912bdd1fd6:@_超 http://blog.csdn.net/cloudox_/article/details/48248651,这个是正确的,另外需要在Capabilities中将KeychainSharing打开
    大慈大悲大熊猫:@小菜超 作为存取的key,用宏并不好,下文已改为static const

本文标题:iOS简单使用keychain存储密码

本文链接:https://www.haomeiwen.com/subject/drdzxttx.html