SSKeychain

Keychain 使用? ---为了实用最大化我觉得我应该直接先说使用!

当然是使用第三方库啦: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":@"属性值N",@"valueData":@数据} 

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.检查是否已经存在 构建的查询用的操作字典:kSecAttrService,kSecAttrAccount,kSecClass(标明存储的数据是什么类型,值为kSecClassGenericPassword 就代表一般的密码)

   2.添加用的操作字典: kSecAttrService,kSecAttrAccount,kSecClass,kSecValueData

   3.更新用的操作字典1(用于定位需要更改的钥匙):kSecAttrService,kSecAttrAccount,kSecClass 

        操作字典2(新信息)kSecAttrService,kSecAttrAccount,kSecClass ,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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/393491.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux mysql提交_MySQL 事务提交过程

开发老大要求通过binlog查询一条被修改的数据&#xff0c;数据被查出后问我&#xff0c;有没有可能binlog中不会记录&#xff0c;回答不会&#xff0c;因为数据被修改&#xff0c;若失败直接回滚&#xff0c;不会在binlog中记录&#xff0c;此刻一个朋友用了洪荒之力告诉我&…

React单元测试:Jest + Enzyme(二)

前言 在上一篇教程中&#xff0c;我们成功搭建了基于Jest和Enzyme的单元测试框架并成功地跑起来第一个单元测试&#xff0c;可以点击这里回顾一下。今天&#xff0c;我们重点讨论如何通过Jest来mock数据。 什么是Mock Mock的简单翻译就是模拟。既可以模拟数据&#xff0c;也可以…

python dict hash算法_2020年3月26日python学习笔记——hash

什么是哈希&#xff1f;hash,一般翻译做散列、杂凑&#xff0c;或音译为哈希&#xff0c;是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出&#xff0c;该输出就是散列值。这种转换是一种压缩映射&#xff0c;也就是&#xff0c;散列值的空间通常远…

数据处理不等式:Data Processing Inequality

我是在差分隐私下看到的&#xff0c;新解决方案的可用性肯定小于原有解决方案的可用性&#xff0c;也就是说信息的后续处理只会降低所拥有的信息量。 那么如果这么说的话为什么还要做特征工程呢&#xff0c;这是因为该不等式有一个巨大的前提就是数据处理方法无比的强大&#x…

gulp 实现sass自动化 ,监听同步

实现功能 监听scss文件   sass自动化 准备条件 1 .安装gulp npm init ---->一直enter&#xff0c;会在当前目录下生成一个package.json文件,记录安装的依赖模块 npm install gulp --save-dev 2 .安装gulp-ruby-sass npm install gulp-ruby-sass 你还需要安装ruby环境…

MSSQL → 02:数据库结构

一、数据库的组成 在SQL Server 2008中&#xff0c;用户如何访问及使用数据库&#xff0c;就需要正确了解数据库中所有对象及其设置。数据库就像一个容器&#xff0c;它里面除了存放着数据的表之外&#xff0c;还有视图、存储过程、触发器、约束等数据库对象。数据库管理的核心…

mySQL教程 第9章 触发器

第9章 触发器 入的新数据放到new表&#xff0c;删除的数据放到old表。 准备本章学习环境 连接数据库schoolDB&#xff0c;删除表TStudent&#xff0c;TScore和Tsubject中的所有数据。 delete from TStudent; delete from TScore; delete from TSubject; 向学生表插入两条记录 i…

掩码图制作photoshop__新手用

1.首先你得有一张图&#xff0c;比如这样的&#xff1a; 2.用PS打开他 3.左边工具栏里&#xff08;快速选择工具W&#xff09;&#xff0c;选想显示的部分 4.ctrlc复制一下&#xff0c;新建一张黑底图粘贴上去或者白底图时选中显示区即花瓣右键反向右键填充成黑色 5.菜单栏->…

Unity3D手机斗地主游戏开发实战(02)_叫地主功能实现

大体思路 前面我们实现了点击开始游戏按钮&#xff0c;系统依次给玩家发牌的逻辑和动画&#xff0c;并展示当前的手牌。这期我们继续实现接下来的功能--叫地主。 1.首先这两天&#xff0c;学习了DOTween&#xff0c;这是一个强大的Unity动画插件&#xff0c;大家可以参考&#…

Koa 中实现 chunked 数据传输

有关于 Transfer-Encoding:chunked 类型的响应&#xff0c;参见之前的文章HTTP 响应的分块传输。这里看 Koa 中如何实现。 Koa 中请求返回的处理 虽然官方文档有描述说明不建议直接调用 response.write&#xff1a; Bypassing Koas response handling is not supported. Avoid …

HTML5新特性之Mutation Observer

Mutation Observer&#xff08;变动观察器&#xff09;是监视DOM变动的接口。当DOM对象树发生任何变动时&#xff0c;Mutation Observer会得到通知。 要概念上&#xff0c;它很接近事件。可以理解为&#xff0c;当DOM发生变动会触发Mutation Observer事件。但是&#xff0c;它与…

Python操作MongoDB - 极简教程

2019独角兽企业重金招聘Python工程师标准>>> Python 连接 MongoDB 安装PyMongo模块 pip install pymongo使用MongoClient建立连接 from pymongo import MongoClient # 以下为三种建立连接的方式 #client MongoClient() #client MongoClient(localhost, 27017) #cl…

java 省市区三级联动_AJAX省市区三级联动下拉菜单(java版)

此小程序的功能主要是采用异步请求方式从数据库中调取省市区信息显示到下拉列表&#xff1a;代码如下&#xff1a;建立数据库中的代码和一些配置文件信息就省略了&#xff0c;主要有JavaScript中的代码为&#xff1a;$(document).ready(function(){$.get("getProvince.do&…

20155305乔磊2016-2017-2《Java程序设计》第四周学习总结

20155305乔磊2016-2017-2《Java程序设计》第四周学习总结 教材学习内容总结 继承 继承就是避免多个类间重复定义共同行为。面向对象中&#xff0c;子类继承父类&#xff0c;就是把程序中相同的代码部分提升为父类。extends关键字&#xff0c;表示前者会扩充后者的行为&#xff…

【eclipse转idea的第一天】配置idea

为什么80%的码农都做不了架构师&#xff1f;>>> 导入maven项目 设置maven(全局) 为了不然才转idea的码友们重复我犯过的错&#xff0c;我这儿截图步骤说明下&#xff1a; 这里是列表文本这里是列表文本idea的设置有两种&#xff1a;全局&#xff0c;局部(我这么叫的…

Vmware 安装虚拟工具 (二)

打开虚拟机&#xff0c;以root超级用户登陆&#xff0c;菜单栏选择虚拟机&#xff0c;install安装虚拟机 拷贝虚拟工具到 在根目录下建立文件夹&#xff0c;并将工具拷贝到该文件夹&#xff0c;例如vmtool 打开终端&#xff0c;进入该目录开始安装 如图&#xff0c;进入目录解压…

git与svn的区别 ?Git 与 SVN那个更好?

git与svn的区别 &#xff1a; http://www.360doc.com/content/12/1228/20/11220452_256857021.shtml 在版本控制系统的选型上&#xff0c;是选择Git还是SVN&#xff1f; 对于开源项目来说这不算问题。使用Git极大地提高了开发效率、扩大了开源项目的参与度、 增强了版本控制系统…

利用Arcgis for javascript API绘制GeoJSON并同时弹出多个Popup

1.引言 由于Arcgis for javascript API不可以绘制Geojson&#xff0c;并且提供的Popup一般只可以弹出一个&#xff0c;在很多专题图制作中&#xff0c;会遇到不少的麻烦。因此本文结合了两个现有的Arcgis for javascript API扩充库&#xff0c;对其进行改造达到绘制Geojson并同…

HBase数据备份及恢复(导入导出)的常用方法

一、说明 随着HBase在重要的商业系统中应用的大量增加&#xff0c;许多企业需要通过对它们的HBase集群建立健壮的备份和故障恢复机制来保证它们的企业&#xff08;数据&#xff09;资产。备份Hbase时的难点是其待备份的数据集可能非常巨大&#xff0c;因此备份方案必须有很高的…

Android商城开发系列(二)——App启动欢迎页面制作

商城APP一般都会在应用启动时有一个欢迎界面&#xff0c;下面我们来实现一个最简单的欢迎页开发&#xff1a;就是打开商城App&#xff0c;先出现欢迎界面&#xff0c;停留几秒钟&#xff0c;自动进入应用程序的主界面。 首先先定义WelcomeActivity布局&#xff0c;布局非常简单…