iOS 数据持久化之KeyChain(Swift Demo)

原创blog,转载请注明出处

blog.csdn.net/hello_hwc?viewmode=list



前言:前两篇持久化分别讲到了

本文讲解如何保存需要加密的信息。绝大多数情况下都是保存密码。少数情况下需要保存证书等信息。本文以密码为例,讲解如何用iOS SDK原生API来进行KeyChain的操作。

实际开发的过程中,建议使用一些Github的集成库,或者自己写一个KeyChain的库,很简单

源代码提供Swift版本,完整工程下载

CSDN下载

http://download.csdn.net/detail/hello_hwc/8663811

GitHub

https://github.com/wenchenhuang/SwiftKeyChainDemo



Demo效果

四个按键对应添加,更新,获取,删除

Demo的password没有显示黑点,是为了方便查看。

四种操作

---Get----


KeyChain简介

KeyChain是一个加密的容器,通常用来保存密码,证书,和一些需要加密的key。对于iOS来说,每个App有独立的keyChain,每个app只能访问自己的keyChain.

注意:keyChain的访问权限依赖于provisioning file。所以,如果要在应用更新的时候,仍然能够访问之前保存的密码,要保证provisioning file是同一个文件。


KeyChain描述

keyChain是通过字典来描述的,是一组key-value的对。用来描述这个keyChain是为什么样的应用保存什么样的数据,有什么样的访问权限等等。

一个典型的字典

其中

  • kSecClass 表示存储的是密码
  • kSecAttrAccount 表示的是为IamUser这个账号存储的密码
  • kSecAttrService 表示是为App Store存储的账号
  • 其余两个在查询的时候使用,知道如果要查询都设为ture就可以了

所有的keys可以从以下链接获取

https://developer.apple.com/library/ios/documentation/Security/Reference/keychainservices/index.html


手把手教你建立Demo App

创建一个基于Swift的工程,然后在storyboard上拖拽控件

并且拖拽outlet和action,然后实现UITextFieldDelegate,保证我们点击Return的时候,键盘会消失。这时候的代码如下

import Security

class ViewController: UIViewController,UITextFieldDelegate{

    @IBOutlet weak var usernameTextfield: UITextField!
    @IBOutlet weak var passwordTextField: UITextField!

    @IBAction func addKeyChainItem(sender: AnyObject) {
    }

    @IBAction func updateKeyChainItem(sender: AnyObject) {
    }

    @IBAction func getKeyChainItem(sender: AnyObject) {
    }

    @IBAction func deleteKeyChainItem(sender: AnyObject) {
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        usernameTextfield.delegate = self
        passwordTextField.delegate = self
        // Do any additional setup after loading the view, typically from a nib.
    }
    func textFieldShouldReturn(textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }
}


然后,添加几个个辅助方法,减少我们的代码量

创建默认的描述字典

    func createDefaultKeyChainItemDic()->NSMutableDictionary{
        var keyChainItem = NSMutableDictionary()
        keyChainItem.setObject(kSecClassInternetPassword as NSString, forKey: kSecClass as NSString)
        keyChainItem.setObject("blog.csdn.net/hello_hwc", forKey:  kSecAttrServer as NSString)
        keyChainItem.setObject(self.usernameTextfield.text, forKey: kSecAttrAccount as NSString)
        return keyChainItem
    }

用UIAlertController提示信息

 func alertWithMessage(message:String){
        var alertController = UIAlertController(title:"Info", message: message, preferredStyle: UIAlertControllerStyle.Alert)
        alertController.addAction(UIAlertAction(title:"OK", style: UIAlertActionStyle.Cancel, handler:nil))
        self.presentViewController(alertController, animated: true, completion: nil)
    }
    func alertWithStatus(status:OSStatus){
        if(status == 0){
            self.alertWithMessage("Success")
        }else{
            self.alertWithMessage("Fail ErrorCode is\(status)")
        }
    }

添加KeyChain

  • 这里用函数SecItemCopyMatching来查找这个keyChain是否存在。两个参数,第一个是描述字典,第二个是查找结果拷贝到的字典,通常只有在获取的时候才会用到,这里为nil即可。
  • kSecValueData这个key是实际要保存的密码,要先转换成NSData
  • SecItemAdd这个函数来添加keyChain,返回值是OSStatus类型,错误类型较多,可以Google。这里知道0是没有错误就可以了。
  @IBAction func addKeyChainItem(sender: AnyObject) {
        var keyChainItem = self.createDefaultKeyChainItemDic()
        if SecItemCopyMatching(keyChainItem,nil) == noErr{
            self.alertWithMessage("User name already exits")
        }else{
            keyChainItem.setObject(self.passwordTextField.text.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion:true)!, forKey: kSecValueData as String)
            var status = SecItemAdd(keyChainItem, nil)
            self.alertWithStatus(status)
        }
    }

更新KeyChain

SecItemUpdate函数用来更新KeyChain,两个参数,第一个参数是描述字典,第二个是包含更新数据的字典

  @IBAction func updateKeyChainItem(sender: AnyObject) {
         var keyChainItem = self.createDefaultKeyChainItemDic()
        if SecItemCopyMatching(keyChainItem,nil) == noErr{
            var updateDictionary = NSMutableDictionary()    updateDictionary.setObject(self.passwordTextField.text.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion:true)!, forKey:kSecValueData as String)
            var status = SecItemUpdate(keyChainItem,updateDictionary)
            self.alertWithStatus(status)
        }else{
            self.alertWithMessage("The keychain doesnot exist")
        }
    }

删除keyChain

SecItemDelete函数用来删除

    @IBAction func deleteKeyChainItem(sender: AnyObject) {
        var keyChainItem = self.createDefaultKeyChainItemDic()
        if SecItemCopyMatching(keyChainItem,nil) == noErr{
            let status = SecItemDelete(keyChainItem)
            self.alertWithStatus(status)
        }else{
            self.alertWithMessage("The keychain doesnot exist")

        }
    }

获取KeyChain

SecItemCopyMatching第二个参数包含了获取到的字典信息。转换方式有点复杂。


    @IBAction func getKeyChainItem(sender: AnyObject) {
        var keyChainItem = self.createDefaultKeyChainItemDic()
        keyChainItem.setObject(kCFBooleanTrue, forKey: kSecReturnData as String)
        keyChainItem.setObject(kCFBooleanTrue, forKey: kSecReturnAttributes as String)
        var queryResult: Unmanaged<AnyObject>?
        let status = SecItemCopyMatching(keyChainItem,&queryResult)
        let opaque = queryResult?.toOpaque()
        var contentsOfKeychain: NSString?
        if let op = opaque {
            let retrievedData = Unmanaged<NSDictionary>.fromOpaque(op).takeUnretainedValue()
            let passwordData = retrievedData.objectForKey(kSecValueData) as! NSData
            let passwordString = NSString(data: passwordData, encoding: NSUTF8StringEncoding)!
            self.alertWithMessage("Password: \(passwordString)")
        }else{
            self.alertWithMessage("The keychain doesnot exist")
        }
    }

总结

简单来讲,一共就是四个函数

  1. SecItemCopyMatching - 查询和获取
  2. SecItemUpdate - 更新
  3. SecItemAdd - 添加
  4. SecItemDelete - 删除


欢迎关注我的iOS详解专栏,这里我会讲解绝大部分iOS常用的技术

http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html

我的博客iOS部分目录

http://blog.csdn.net/hello_hwc/article/details/45365385

时间: 2024-10-31 02:24:19

iOS 数据持久化之KeyChain(Swift Demo)的相关文章

iOS开发笔记-swift实现iOS数据持久化之归档NSKeyedArchiver

IOS数据持久化的方式分为三种: 属性列表 (plist.NSUserDefaults) 归档 (NSKeyedArchiver) 数据库 (SQLite.Core Data.第三方类库等 归档(又名序列化),把对象转为字节码,以文件的形式存储到磁盘上:程序运行过程中或者当再次重写打开程序的时候,可以通过解归档(反序列化)还原这些对象.本文主要介绍swift实现iOS数据归档. 归档Foundation框架对象 func archiveData(){ var path: AnyObject=NS

iOS -数据持久化方式-以真实项目讲解

前面已经讲解了SQLite,FMDB以及CoreData的基本操作和代码讲解(CoreData也在不断学习中,上篇博客也会不断更新中).本篇我们将讲述在实际开发中,所使用的iOS数据持久化的方式以及怎么会使用到这些方式,都会以本人实际开发的场景为例,大约需要花10-15分钟,欢迎大家指正. 一.前言 和大家说一个真实故事,前年我去美图面试(当时的技术仅仅是UI和接口的实现,并不注重很多底层实现和很多概念的原理,换句话说,就是真正的码农),过了技术第一轮和第二轮(前两年的也就是问问技术点的实现),

iOS数据持久化存储

本文中的代码托管在github上:https://github.com/WindyShade/DataSaveMethods 相对复杂的App仅靠内存的数据肯定无法满足,数据写磁盘作持久化存储是几乎每个客户端软件都需要做的.简单如"是否第一次打开"的BOOL值,大到游戏的进度和状态等数据,都需要进行本地持久化存储.这些数据的存储本质上就是写磁盘存文件,原始一点可以用iOS本身支持有NSFileManager这样的API,或者干脆C语言fwrite/fread,Cocoa Touch本身

IOS数据持久化之归档NSKeyedArchiver

IOS数据持久化的方式分为三种: 属性列表 (自定义的Property List .NSUserDefaults) 归档 (NSKeyedArchiver) 数据库 (SQLite.Core Data.第三方类库等) 下面主要来介绍一个归档NSKeyedArchiver. 归档(又名序列化),把对象转为字节码,以文件的形式存储到磁盘上:程序运行过程中或者当再次重写打开程序的时候,可以通过解归档(反序列化)还原这些对象. 归档方式: 对Foundation框架中对象进行归档 对自定义的内容进行归档

iOS数据持久化方式分析

iOS数据持久化的方式一般为:plist文件写入.对象归档.SQLite数据库.CoreData. plist文件写入.对象归档一般用于小的数据量. SQLite数据库.CoreData则用于大的数据量. SQLite是一款轻型的数据库,是一种关系型数据库管理系统,他的设计目的是嵌入式设备中使用. SQLite占用资源非常低,非常适合移动设备中使用,而且是开源免费的 SQLite的数据库操作其实和常规的数据库操作流程是一样的: 1.打开数据库 sqlite3_open() 2.准备SQL语句,采

iOS数据持久化之二——归档与设计可存储化的数据模型基类

iOS数据持久化之二--归档与设计可存储化的数据模型基类 一.引言 在上一篇博客中,我们介绍了用plist文件进行数据持久化的方法.虽然简单易用,但随着开发的深入,你会发现,这种方式还是有很大的局限性.试想,如果我们可以将用户的登录返回信息模型,游戏中角色的属性信息模型进行直接的持久化存取,那是不是非常爽的事,幸运的是,我们可以通过归档,来设计一个这样的数据模型. 二.先来精通归档吧 归档也是iOS提供给开发者的一种数据存储的方式,事实上,几乎所有的数据类型都可以通过归档来进行存取.其存储与读取

iOS 数据持久化之NSUserDefaults

原创Blog,转载请注明 blog.csdn.net/hello_hwc 前言:iOS的数据持久化存储分为很多种 普通文件,plist NSUserDefaults CoreData KeyChain 本文讲解NSUserDefaults的使用 StandardUserDefaults 大部分的时候使用StandardUserDefaults来保存数据,这是一个共享的UserDefaults,意味着在程序的任意一个地方访问到的都是同一个UserDefaults 写数据 swift代码 var u

iOS 数据持久化4种方式

iOS 4种讲数据持久存储到iOS文件的系统机制: 属性列表(NSUserDefaults.plist文件) 对象归档(NSCoding) iOS嵌入式关系数据库(SQLite3) 苹果提供的持久化工具(Core Data) 说道数据持久化都涉及到一个共同的要素.既然是把数据持久存储到iOS文件系统中,那么久涉及到了应用沙盒. 可以尝试使用Xcode建立一个空的应用,然后打开应用目录可以查看到有以下文件 1.Documents ①存放内容 我们可以将应用程序的数据文件保存在该目录下.不过这些数据

IOS数据持久化的4种方式

9.1 数据持久化概述 9.2 iOS应用程序目录结构 9.3 读写属性列表 9.4 对象归档 9.5 访问SQLite 9.1 数据持久化概述 iOS中可以有四种持久化数据的方式: 属性列表.对象归档.SQLite3和Core Data 9.2 iOS应用程序目录结构 iOS应用程序运行在Mac os模拟器时候,有一下临时目录模拟器3.1.3为例子: /Users/tony/Library/Application Support/iPhone Simulator/3.1.3/Applicati