1 keyChainWrapper是MRC代码,要禁用ARC -fno-objc-arc

2 要导入Security.framework框架

3 获得一个不变的UUID

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 判断Keychain中是否存在这条Item如果不存在SecItem就添加。
NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys:
(__bridge NSString *)kSecClassGenericPassword, kSecClass,
@"bundleSeedID", kSecAttrAccount,
@"", kSecAttrService,
                  //设置为True可以配合SecItemCopyMatching属性获得SecItem的信息。有的话
(id)kCFBooleanTrue, kSecReturnAttributes,
nil];
CFDictionaryRef result = nil;
OSStatus status = SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&result);
if (status == errSecItemNotFound)
status = SecItemAdd((CFDictionaryRef)query, (CFTypeRef *)&result);
if (status != errSecSuccess)
return nil;
// 获取AccessGroup即 AppIdentifierPrefix 和 Bundle Id的组合。
NSString *accessGroup = [(__bridge NSDictionary *)result objectForKey:(__bridge NSString *)kSecAttrAccessGroup];
// 初始化(根据标识符获取)一个wrapper
KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"jifeifei" accessGroup:accessGroup];
// account 不存在是初始化出来的,设置 kSecAttrAccount 的 value
NSString *account = [wrapper objectForKey:(id)kSecAttrAccount];
if (!account || account.length == ) {
[wrapper setObject:@"jifeifei" forKey:(id)kSecAttrAccount];
}
// uuid 不存在是初始化出来的 设置 kSecValueData 的 Value
NSString *uuid = [wrapper objectForKey:(id)kSecValueData];
if (!uuid || uuid.length == ) {
uuid = [[[UIDevice currentDevice].identifierForVendor.UUIDString stringByReplacingOccurrencesOfString:@"-" withString:@""] lowercaseString];
[wrapper setObject:uuid forKey:(id)kSecValueData];
} [self attempt]; return YES;
}

4 获得IDFA方法 如果打开限制广告追踪标识符会出现取不到IDFA的情况

  #import <AdSupport/AdSupport.h>

   NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];

5 直接使用KeyChain保存数据

使用keyChain保存数据的三个方法:

    // 添加保存的数据
SecItemAdd(CFDictionaryRef _Nonnull attributes, <#CFTypeRef _Nullable * _Nullable result#>)
// 删除保存的数据
SecItemDelete(<#CFDictionaryRef _Nonnull query#>)
// 更新保存的数据
SecItemUpdate(CFDictionaryRef _Nonnull query, <#CFDictionaryRef _Nonnull attributesToUpdate#>)
// 获取保存的数据
SecItemCopyMatching(<#CFDictionaryRef _Nonnull query#>, <#CFTypeRef _Nullable * _Nullable result#>)
#import <Foundation/Foundation.h>

@interface FFKeyChain : NSObject
+ (void)save:(NSString *)serve data:(id)Data;
+ (id)read:(NSString *)serve;
@end #import "FFKeyChain.h" @implementation FFKeyChain
/* https://blog.csdn.net/zhoushuangjian511/article/details/78583429 https://www.cnblogs.com/whyandinside/p/3303108.html
kSecAttrAccessible: 属性控制keychain中的Item什么时候可以被访问。可选值有 kSecAttrAccessibleWhenUnlocked, kSecAttrAccessibleAfterFirstUnlock, kSecAttrAccessibleAlways, kSecAttrAcessibleWhenUnlockedThisDeviceOnly, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, kSecAttrAccessibleAlwaysThisDeviceOnly
带有ThisDeviceOnly的意思是如果手机使用其他device的备份restore了之后这些Item就不存在了。 kSecAttrAccessGroup: 如果希望,keychain的item可以被多个应用share, 可以给Item设置这个属性, 类型是CFStringRef, 应用程序在被编译时,可以在entitlement中指定自己的accessgroup,如果应用中的accessgroup和keyChain item中的Accessgroup名字一直,那么这个应用就可以访问这个item,缺点是:accessgroup是由开发者指定的,他可以故意跟其他应用的accessgroup一样,已达到访问其他应用item的目的。同事还支持 wild card ,如keychain-dumper将自己的accessgroup指定为*,从而可以把keychain中所有的Item都dump出来。 kSecAttrAccount 必须 指定一个字典键,其值为物品的描述属性, 使用此键设置或获得,CFStringRef, 包含账户名
kSecAttrService 必须 指定一个字典键,其值为物品的描述属性, 使用此键设置或获得,CFStringRef与该项目相关的服务 */ + (NSMutableDictionary *)getKeyChainQuery:(NSString *)serve {
return [@{(id)kSecClass:(id)kSecClassGenericPassword,
(id)kSecAttrAccount:serve,
(id)kSecAttrService:serve,
(__bridge NSString *)kSecAttrAccessible:(__bridge NSString *)kSecAttrAccessibleAfterFirstUnlock,
} mutableCopy];
} +(NSMutableDictionary*)keyChainIdentifier:(NSString*)identifier {
NSMutableDictionary * keyChainMutableDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:(id)kSecClassGenericPassword,kSecClass,identifier,kSecAttrService,identifier,kSecAttrAccount,kSecAttrAccessibleAfterFirstUnlock,kSecAttrAccessible, nil];
return keyChainMutableDictionary;
} + (void)save:(NSString *)serve data:(id)Data {
NSMutableDictionary *mDic = [self keyChainIdentifier:serve];//[self getKeyChainQuery:serve];//;
SecItemDelete((CFDictionaryRef)mDic);
[mDic setObject:[NSKeyedArchiver archivedDataWithRootObject:Data] forKey:(id)kSecValueData];
OSStatus sta = SecItemAdd((__bridge CFDictionaryRef)mDic, NULL);
if (sta == noErr) {
NSLog(@"成功。。");
};
} + (void)delete:(NSString *)serve {
NSMutableDictionary *mdic = [self getKeyChainQuery:serve];
SecItemDelete((__bridge CFDictionaryRef)mdic);
}

+ (void)neeUpdateServe:(NSString *)server updateValue:(NSString *)value {
    NSMutableDictionary *mdic = [self getKeyChainQuery:server];
    OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)mdic, (__bridge CFDictionaryRef)@{(id)kSecValueData:[NSKeyedArchiver archivedDataWithRootObject:value]});
    if (status == errSecSuccess) {
        NSLog(@"更新成功");
    }else {
        NSLog(@"更新失败");
    }
}
+ (id)read:(NSString *)serve {
id let = nil;
NSMutableDictionary *mdic = [self getKeyChainQuery:serve];
[mdic setValue:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
[mdic setValue:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
CFDataRef keyData = nil;
if (SecItemCopyMatching((__bridge CFDictionaryRef)mdic, (CFTypeRef *)&keyData) == noErr) {
@try{
let = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
} @catch (NSException *e) {
NSLog(@"Unarchiver of %@ failed %@", serve, e);
} @finally { }
}
if (keyData) {
CFRelease(keyData);
}
return let; }
@end

KeyChainWrapper - keychain简单使用的更多相关文章

  1. 使用keychain保存用户名和密码等敏感信息 KeychainItemWrapper和SFHFKeychainUtils

    iOS的keychain服务提供了一种安全的保存私密信息(密码,序列号,证书等)的方式,每个ios程序都有一个独立的keychain存储.相对于 NSUserDefaults.文件保存等一般方式,ke ...

  2. IOS开发之----两种保存用户名和密码实现记住密码库

    使用Keychain存储用户敏感信息 iOS的keychain服务提供了一种安全的保存私密信息(密码,序列号,证书等)的方式,每个ios程序都有一个独立的keychain存储.相对于 NSUserDe ...

  3. iOS keyChain(钥匙串)的简单使用

    通常在开发中我们需要长久的保存某些值比如用户的账号密码等,对于隐私度很高的数据来说保证数据的安全性是尤为重要的.ios中的keyChain是一种很好的选择. 首先去开发者网站(https://deve ...

  4. iOS逆向工程之KeyChain与Snoop-it

    今天博客的主题是Keychain, 在本篇博客中会通过一个登陆的Demo将用户名密码存入到KeyChain中,并且查看一下KeyChain中存的是什么东西,把这些内容给导出来.当然本篇博客的重点不是如 ...

  5. iOS上简单推送通知(Push Notification)的实现

    iOS上简单推送通知(Push Notification)的实现 根据这篇很好的教程(http://www.raywenderlich.com/3443/apple-push-notification ...

  6. 【数据库】MySQL的安装与简单使用

    首先我们要下载Mysql的安装包,大家可以到http://mysql.com官网中根据自己的电脑系统版本下载 也可以点击 MySQL资源 下载 密码:btuu 建议下载5.7以上的版本,因为省掉了许多 ...

  7. [iOS Keychain本地长期键值存储]

    目前本地存储方式大致有:Sqlite,Coredata,NSUserdefaults.但他们都是在删除APP后就会被删除,如果长期使用存储,可以使用Keychain钥匙串来实现. CHKeychain ...

  8. iOS 使用Keychain 保存 用户名和密码到 本地

    iOS 使用Keychain 保存 用户名和密码到 本地 之前曾把一些简单的数据保存在了plist,文件,及NsuserDefault里面, 但是如果要保存密码之类的,保存在本地就很不安全了: 但是利 ...

  9. Code Sign error: No unexpired provisioning profiles found that contain any of the keychain's signing certificates

    最近离职了,刚好在离职之际有人叫我帮做个项目,简直了,没有mac电脑,没有真ji设备,简直了.接项目那哥们,暂且叫做J,大哥说我给你想办法,then,给借了个mac pro.刚拿到电脑真是喜出望外啊, ...

随机推荐

  1. php初中高阶段

    多学习PHP的朋友比较关心的问题之一就是学成后就业的薪资问题,关于PHP就业工资我们共同来探讨一下,其实小编觉得,PHP就业工资是多少并不重要,总要的是你的技术值多少钱,只要你的技术很棒,高薪根本就不 ...

  2. [django] Deploy Django Applications Using uWSGI and Nginx on Ubuntu 14.04

    关键点1:chmod-socket=666 (mysite_uwsgi.ini) 关键点2 : 工程目录和虚拟环境目录搞清楚 几个参考: http://uwsgi-docs.readthedocs.i ...

  3. 详解python2 和 python3的区别-乾颐堂

    看到这个题目大家可能猜到了我接下来要讲些什么,呵呵,对了,那就是列出这两个不同版本间的却别!搜索一下大家就会知道,python有两个主要的版本,python2 和 python3 ,但是python又 ...

  4. 【转】Hibernate的getSQLQuery方法对char类型的解析问题

    [转]Hibernate的getSQLQuery方法对char类型的解析问题 建立数据库: create table T_TEST1( id char (32), name varchar (255) ...

  5. 高性能 js -- 无阻塞加载脚本

    参考: <<高性能JavaScript>> Nicbolas C. Zakas 著 javascript代码的下载和执行过程会阻塞浏览器的其他进程, 比如页面的绘制, 遇到&l ...

  6. 2018.08.30 NOIP模拟 kfib(矩阵快速幂+exgcd)

    [输入] 一行两个整数 n P [输出] 从小到大输出可能的 k,若不存在,输出 None [样例输入 1] 5 5 [样例输出] 2 [样例解释] f[0] = 2 f[1] = 2 f[2] = ...

  7. 用org.mybatis.generator 生成代码

    1:引入pom 2:增加生成配置xml: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE ...

  8. Django(4)

    https://www.cnblogs.com/yuanchenqi/articles/7439088.html

  9. 【Unity】1.0 第1章 Unity—3D游戏开发和虚拟现实应用开发的首选

    分类:Unity.C#.VS2015 创建日期:2016-03-23 一.简介 Unity是跨平台2D.3D游戏和虚拟现实高级应用程序的专业开发引擎,是由Unity Technologies公司研制的 ...

  10. 日期 时间选择器(DatePicker和TimePicker)实现用户选择

    日期和时间 作者的设计TimePicker时,大小分布不合理,我调整宽度为match-parent高度为wrap-parent就可以了. public class MainActivity exten ...