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,一经查实,立即删除!

相关文章

shell高级-----正则表达式

正则表达式概述 正则表达式是一种定义的规则&#xff0c;Linux工具可以用它来过滤文本。 基础正则表达式 纯文本 [rootnode1 ~]# echo "this is a cat" | sed -n /cat/p this is a cat [rootnode1 ~]# echo "this is a cat" | gawk /cat/{print $0} this …

leetcode130. 被围绕的区域(bfs)

给定一个二维的矩阵&#xff0c;包含 ‘X’ 和 ‘O’&#xff08;字母 O&#xff09;。 找到所有被 ‘X’ 围绕的区域&#xff0c;并将这些区域里所有的 ‘O’ 用 ‘X’ 填充。 示例: X X X X X O O X X X O X X O X X 运行你的函数后&#xff0c;矩阵变为&#xff1a; X X…

linux mysql提交_MySQL 事务提交过程

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

spray.json_如何使用Spray-json(Un)在Akka HTTP中封送JSON

spray.jsonby Miguel Lopez由Miguel Lopez 如何使用Spray-json(Un)在Akka HTTP中封送JSON (How to (Un)marshal JSON in Akka HTTP with spray-json) In the previous post, we added JSON support to our Akka HTTP API using circe.在上一篇文章中 &#xff0c;我们使用circ…

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

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

input file 文件上传,js控制上传文件的大小和格式

文件上传一般是用jquery的uploadify&#xff0c;比较好用。后面会出文章介绍uploadify这个插件。 但是&#xff0c;有时候为了偷懒&#xff0c;直接就用input 的file进行文件和图片等的上传&#xff0c;input file 可以控制上传的格式&#xff0c;但是是html5&#xff0c;很多浏…

leetcode面试题 17.08. 马戏团人塔(二分法)

有个马戏团正在设计叠罗汉的表演节目&#xff0c;一个人要站在另一人的肩膀上。出于实际和美观的考虑&#xff0c;在上面的人要比下面的人矮一点且轻一点。已知马戏团每个人的身高和体重&#xff0c;请编写代码计算叠罗汉最多能叠几个人。 示例&#xff1a; 输入&#xff1a;…

如何选择适合自己的CMS建站系统

如今做网站已不像过去那样必须找网站公司才能建&#xff0c;因为网上针对建站的各种CMS建站系统层出不穷。像PageAdmin、DEDECMS、帝国CMS、Discuz等&#xff0c;这些CMS系统各有各的特点和优势&#xff0c;小熊优化的小编我从事网站制作和网站优化多年&#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…

aws架构_如何使用AWS构建可扩展架构

aws架构What I learned building the StateOfVeganism ?我学到的建立素食主义的方法是什么&#xff1f; By now, we all know that news and media shape our views on the topics we discuss. Of course, this is different from person to person. Some might be influence…

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环境…

leetcode面试题 10.03. 搜索旋转数组(二分法)

搜索旋转数组。给定一个排序后的数组&#xff0c;包含n个整数&#xff0c;但这个数组已被旋转过很多次了&#xff0c;次数不详。请编写代码找出数组中的某个元素&#xff0c;假设数组元素原先是按升序排列的。若有多个相同元素&#xff0c;返回索引值最小的一个。 示例1: 输入…

MSSQL → 02:数据库结构

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

JAVA拳皇_拳皇(Java简单的小程序)代码实例|chu

刚开始学习Java&#xff0c;看完老九君的视频根据他的内容敲的代码&#xff0c;感觉还挺有成就感的&#xff0c;毕竟刚学习Java。package helloasd;import java.util.*; public class hellojava { public static void main(String[] args) { Scanner input new Scanner(System…

mySQL教程 第9章 触发器

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

vue使用python_如何使用Python和Vue创建两人游戏

vue使用pythonby Neo Ighodaro由新Ighodaro 如何使用Python和Vue创建两人游戏 (How to create a two-player game with Python and Vue) In this tutorial, we will create a realtime tic-tac-toe game using Python and Pusher channels. Here’s a demo of how the game wi…

掩码图制作photoshop__新手用

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

leetcode287. 寻找重复数(二分法)

给定一个包含 n 1 个整数的数组 nums&#xff0c;其数字都在 1 到 n 之间&#xff08;包括 1 和 n&#xff09;&#xff0c;可知至少存在一个重复的整数。假设只有一个重复的整数&#xff0c;找出这个重复的数。 示例 1: 输入: [1,3,4,2,2] 输出: 2 代码 class Solution {…

os-enviroment

pip3 install PyUserInput ping 是不带协议的转载于:https://www.cnblogs.com/liuweimingcprogram/p/10957592.html