(转)iOS keychain API及其封装
一. Keychain API
KeyChain中item的结构为:
1.增加keychain Item
OSStatus SecItemAdd (CFDictionaryRef attributes,CFTypeRef *result);
attributes字典中包括增加items的类型键值对和对应类型的属性键值对。item类型键常量为kSecClass,可能的取值为通用密码(kSecClassGenericPassword),网络密码(kSecClassInternetPassword),证书(kSecClassCertificate),密匙(kSecClassKey),ID(带有密匙的证书kSecClassIdentity)。每种类型的item具有不同的可选属性,具体可见Keychain Item Class Keys and Values
若增加item成功,result则为新增加item的引用,其具体类型由attributes中的特定键指定。
- 若kSecReturnData设置为kCFBooleanTrue,则result类型为CFDataRef;
- 若kSecReturnAttributes设置为kCFBooleanTrue,则result类型为CFDictionaryRef;
- 若kSecReturnRef设置为kCFBooleanTrue,则result类型为SecKeychainItemRef, SecKeyRef,SecCertificateRef, 或SecIdentityRef,当返回类型没有显式设置时,则默认为此设置。
- 若kSecReturnPersistentRef设置为kCFBooleanTrue,则result类型为持久存储的CFDataRef,持久存储的CFDataRef可存储在磁盘或在进程之间传递。
- 若以上多个返回类型被设置,则返回CFDictionaryRef类型。
2.查询keychain item
OSStatus SecItemCopyMatching (CFDictionaryRef query,CFTypeRef *result);
根据query指定的属性查找item,并将结果存储在result中。
3.删除item
OSStatus SecItemDelete (CFDictionaryRef query);
删除query指定的item.
4.更新item
OSStatus SecItemUpdate (CFDictionaryRef query,CFDictionaryRef attributesToUpdate);
将query指定的item中的属性按照attributesToUpdate中的数据更新。
参考:
iOS 的keyChain
Keychain Services Reference
二.封装方式一:KeychainWrapper
1. +(NSMutableDictionary *)setupSearchDirectoryForIdentifier:(NSString *)identifier;
所有以下操作的基础,设置在增加、查找、更新、删除items时的通用属性字典。
设置内容伪码如下:
kSecClass = kSecClassGenericPassword;
kSecAttrService = APP_NAME(应用标示符);
kSecAttrGeneric = [identifier dataUsingEncoding:NSUTF8StringEncoding];
kSecAttrAccount = [identifier dataUsingEncoding:NSUTF8StringEncoding];
2. +(NSData *)searchKeychainCopyMatchingIdentifier:(NSString *)identifier;
调用SecItemCopyMatching获取与identifier匹配的item内容,返回类型为kSecReturnData。
使用的查找属性:
kSecMatchLimit = kSecMatchLimitOne;
kSecReturnData = kCFBooleanTrue;
3. +(NSString *)keychainStringFromMatchingIdentifier:(NSString *)identifier;
将searchKeychainCopyMatchingIdentifier:identifier获取的NSData结果转换为字符串。
[[NSString alloc] initWithData:valueData encoding:NSUTF8StringEncoding];
4. +(BOOL)createKeychainValue:(NSString *)value forIdentifier:(NSString *)identifier;
调用SecItemAdd增加新的item.
kSecValueData = (NSData*)value;
kSecAttrAccessible = kSecAttrAccessibleWhenUnlocked;
或identifier匹配的item已存在,则使用updateKeychainValue:forIdentifier更新item的data。
5. +(BOOL)updateKeychainValue:(NSString *)value forIdentifier:(NSString *)identifier;
调用SecItemUpdate将identifier匹配的items的kSecValueData内容修改为(NSData*)value。
6. +(void)deleteItemFromKeychainWithIdentifier:(NSString *)identifier;
调用SecItemDelete删除identifier匹配的item。
SourceCode:
KeychainWrapper.h
KeychainWrapper.m
参考:
Basic Security in iOS 5 Tutorial Part 1
Basic Security in iOS 5 Tutorial Part 2
三.封装方式二:SFHFKeychainUtils
1.+(NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error;
获取serviceName和username匹配的item数据.
查找属性字典:
kSecClass = kSecClassGenericPassword;
kSecAttrAccount = username;
kSecAttrService = serviceName;
首先使用kSecReturnAttributes = kCFBooleanTrue;查找属性值是否存在。
若属性存在,则使用kSecReturnData = kCFBooleanTrue;获取data即密码字段,并转换称NSString返回。
属性存在,而密码不存在时返回特殊的错误码。
2.+(BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error;
设置serviceName和username的密码为password。
已存在则update(SecItemUpdate),不存在则add(SecItemAdd)。
kSecClass = kSecClassGenericPassword;
kSecAttrService = serviceName;
kSecAttrLabel = serviceName;
kSecAttrAccount = username;
kSecValueData = [password dataUsingEncoding: NSUTF8StringEncoding];
3.+(BOOL) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error;
删除serviceName,username对应的item。
使用方式:
存储用户名/密码对,通过用户名获取到对应的密码
#import “SFHFKeychainUtils.h”
//Store new Password in keychain
NSError *error = nil;
NSString *username = usernameFiled.text;
NSString *password = passwordField.text;
[SFHFKeychainUtils storeUsername:username andPassword:password forServiceName:@"myApp",updateExisting:TRUE error:&err];
//Get password from keychain
NSError *error = nil;
NSString *username = @"xuguoxing";
password = [SFHFKeychainUtils getPasswordForUsername:username andServiceName:@"myApp",error:&err];
SourceCode:
https://github.com/ldandersen/scifihifi-iphone/tree/master/security/
SFHFKeychainUtils.h
SFHFKeychainUtils.m
参考:
Simple iPhone Tutorial: Password Management using the keychain by using SFHFKeychainUtils
三.封装方式三:苹果提供的KeychainItemWrapper
- (id)initWithIdentifier: (NSString *)identifier accessGroup:(NSString *) accessGroup;
- (void)setObject:(id)inObject forKey:(id)key;
- (id)objectForKey:(id)key;
- (void)resetKeychainItem;
使用方式:
每个keychain用Identifier标示,根据keychain的各种key设置value,同时可以根据key获取到value。
KeychainItemWrapper* keychain = [[KeychainItemWrapper alloc] initWithIdentifier:@"KeychainTest" accessGroup:nil];
[keychain setObject:kSecAttrAccessibleWhenUnlocked forKey:kSecAttrAccessible];
NSLog(@"%@, %@", [keychain objectForKey:kSecAttrAccount], [keychain objectForKey:kSecValueData]);
[keychain setObject:@"example@email.com" forKey:kSecAttrAccount];
[keychain setObject:@"MySuperSecretPassword" forKey:kSecValueData];
[keychain release];
SourceCode:
KeychainItemWrapper.h
KeychainItemWrapper.m
参考:
GenericKeychain
Using the Keychain to store passwords on iOS
本文出自 清风徐来,水波不兴 的博客,转载时请注明出处及相应链接。
本文永久链接: http://www.winddisk.com/2012/04/09/keychain-api%e5%8f%8a%e5%85%b6%e5%b0%81%e8%a3%85/
(转)iOS keychain API及其封装的更多相关文章
- 聊聊iOS Keychain
某天,小熊碰见这样一个错误 Couldn't update the Keychain Item问题处理 ,网上搜索了下网上很多解决方案,依然百撕不得骑姐.后来参考下面两篇文章.才发现是用法不正确,网上 ...
- iOS - keychain 详解及变化
keychain介绍 iOS keychain 是一个相对独立的空间,保存到keychain钥匙串中的信息不会因为卸载/重装app而丢失, .相对于NSUserDefaults.plist文件保存等一 ...
- iOS开发API常用英语名词
iOS开发API常用英语名词 0. indicating 决定 1.in order to 以便 2.rectangle bounds 矩形尺寸 3.applied 应用 4.entirety 全部 ...
- 基于iOS 10、realm封装的下载器
代码地址如下:http://www.demodashi.com/demo/11653.html 概要 在决定自己封装一个下载器前,我本以为没有那么复杂,可在实际开发过程中困难重重,再加上iOS10和X ...
- class-dump获取iOS私有api
转自:http://blog.csdn.net/sunyuanyang625/article/details/41440167 获取各类iOS私有api 安装工具class-dump 资源地址http ...
- iOS开发拓展篇—封装音频文件播放工具类
iOS开发拓展篇—封装音频文件播放工具类 一.简单说明 1.关于音乐播放的简单说明 (1)音乐播放用到一个叫做AVAudioPlayer的类 (2)AVAudioPlayer常用方法 加载音乐文件 - ...
- Atitit. C# java 的api 目录封装结构映射总结
Atitit. C# java 的api 目录封装结构映射总结 C# java ref System.Reflection System.Type, java.lang.ref concurrent ...
- 如何在 Swift 语言下使用 iOS Charts API 制作漂亮图表?
[编者按]本文作者 Joyce Echessa 是渥合数位服务创办人,毕业于台湾大学,近年来专注于协助客户进行 App 软体以及网站开发.文中作者通过示例介绍用 ios-charts 库创建简易美观的 ...
- 在eclipse中API的封装和调用
自己写的API的封装和调用:1.写好api的方法的实现类.2.抽取一个javadoc文档.file->Export->java->javadoc->finish->Yes ...
随机推荐
- linux grep常用参数
# grep [-acinv] [--color=auto] '搜寻字符串' filename选项与参数:-c :计算找到 '搜寻字符串' 的次数-i :忽略大小写的不同,所以大小写视为相同-n :顺 ...
- html 第一阶段 学习使用总结
基本使用内容: <html> <head> <title>Title of the document</title> <link rel=&quo ...
- 画年利率 画图 自定义 View
使用 SlbSyView slbView; slbView = (SlbSyView) findViewById(R.id.slbView); slbView.setHeights(new float ...
- 7、第七节课,js逻辑运算
1.条件语句 function MyClick() { ; ; ; if (iNum1==iNum2) { iNum2=iNum3; } alert(iNum2); } 2. iNum3=iNum1& ...
- HTTP状态码(HTTP Status codes)简介
HTTP可能大家都熟悉,就是超文本传输协议.浏览器通过HTTP与WEB Server通讯(也有一些其它软件比如IM使用HTTP协议传递数据),把我们的请求(HTTP Request)传递给服务器,服务 ...
- C#线程 访问资源同步简介
在多线程应用(一个或多个处理器)的计算中会使用到同步这个词.实际上,这些应用程序的特点就是它们拥有多个执行单元,而这些单元在访问资源的时候可能会发生冲突.线程间会共享同步对象,而同步对象的目的在于能够 ...
- Regex.Escape
C# 字符串变量str 的值为"a\nb"如果直接输出显示的话,就成了:ab需要输出显示为:a\nb问,怎么办?千万别告诉我定义: str=@"a\nb",因为 ...
- TFS统计编码行数语句
****** Script for SelectTopNRows command from SSMS ******/ SELECT TeamProjectProjectNodeName 项目名称 ,c ...
- 控制弹出div显示在鼠标附近的位置
前一个页面: $("#txt_ocname").click(function () { art.dialog.open("/SelPosAll.aspx", { ...
- poj1182 并查集
题目连接:http://poj.org/problem?id=1182 基础并查集,需要维护与根节点关系,解析见代码: /* poj 1182 并查集 思路分析:让你分析这些话里面多少假的 只需要用 ...