美文网首页花落√莫相思swiftiOS 的那些事儿
82-Swift之密码管理(Keychain)的介绍和使用

82-Swift之密码管理(Keychain)的介绍和使用

作者: NetWork小贱 | 来源:发表于2017-11-21 14:25 被阅读77次

引言

App的开发中,用户登录的模块是必不可少的。用户登录一次之后,就可以使用自动登录功能。自动登录需要知道用户的账号和密码。那么用户的账户和密码是保密性的,为实现App的自动登录功能,我们要稳妥的管理好用户的账号和密码的安全。所以 Keychain 就被使用的上了。下面将给你介绍 Keychain 是什么、如何使用等。友情链接:Object-C 版的密码管理 Keychain 的连接地址 iOS的密码管理系统 Keychain的介绍和使用

Keychain 是什么?

Keychain 是苹果公司 Mac OS(也包含 Mac OSX) 中的密码管理系统。

Keychain 的作用是什么?

Keychain 可以包含许多种类型的数据:密码(包括网站、FTP服务器、SSH账户、网络共享、无线网络、群组软件、加密磁盘镜像),私钥,电子证书、加密笔记等。

Keychain 的四个方法的介绍

1、数据的存储方法

@available(iOS 2.0, *)
public func SecItemAdd(_ attributes: CFDictionary, _ result: UnsafeMutablePointer<CoreFoundation.CFTypeRef?>?) -> OSStatus

@ attributes  : 要存储的数据。
@ result : 存储数据后,返回的指向该数据的引用。

2、根据查询条件获取数据

@available(iOS 2.0, *)
public func SecItemCopyMatching(_ query: CFDictionary, _ result: UnsafeMutablePointer<CoreFoundation.CFTypeRef?>?) -> OSStatus

@ query  :  获取数据的查询条件。
@ result  :  查询后获取到数据的引用。

3、更新数据

@available(iOS 2.0, *)
public func SecItemUpdate(_ query: CFDictionary, _ attributesToUpdate: CFDictionary) -> OSStatus

@ query : 要更新数据的查询条件。
@ attributesToUpdate : 要更新的数据内容。

4、删除数据

@available(iOS 2.0, *)
public func SecItemDelete(_ query: CFDictionary) -> OSStatus

@ query : 删除数据的查询条件。

总结,以上四个方法,就是 Keychain 的增、删、改、查的四个基本方法。这四个方法基本满足大部分App的使用需求。

Keychain 的整理和封装为一个类: KeychainManager.swift

KeychainManager.swift 的完整代码展示:

//
//  KeychainManager.swift
//  KeyChain
//
//  Created by MAC on 2017/11/20.
//  Copyright © 2017年 NetworkCode小贱. All rights reserved.
//

import UIKit

class KeychainManager: NSObject {
    // TODO: 创建查询条件
    class func createQuaryMutableDictionary(identifier:String)->NSMutableDictionary{
        // 创建一个条件字典
        let keychainQuaryMutableDictionary = NSMutableDictionary.init(capacity: 0)
        // 设置条件存储的类型
        keychainQuaryMutableDictionary.setValue(kSecClassGenericPassword, forKey: kSecClass as String)
        // 设置存储数据的标记
        keychainQuaryMutableDictionary.setValue(identifier, forKey: kSecAttrService as String)
        keychainQuaryMutableDictionary.setValue(identifier, forKey: kSecAttrAccount as String)
        // 设置数据访问属性
        keychainQuaryMutableDictionary.setValue(kSecAttrAccessibleAfterFirstUnlock, forKey: kSecAttrAccessible as String)
        // 返回创建条件字典
        return keychainQuaryMutableDictionary
    }
    
    // TODO: 存储数据
    class func keyChainSaveData(data:Any ,withIdentifier identifier:String)->Bool {
        // 获取存储数据的条件
        let keyChainSaveMutableDictionary = self.createQuaryMutableDictionary(identifier: identifier)
        // 删除旧的存储数据
        SecItemDelete(keyChainSaveMutableDictionary)
        // 设置数据
        keyChainSaveMutableDictionary.setValue(NSKeyedArchiver.archivedData(withRootObject: data), forKey: kSecValueData as String)
        // 进行存储数据
        let saveState = SecItemAdd(keyChainSaveMutableDictionary, nil)
        if saveState == noErr  {
            return true
        }
        return false
    }

    // TODO: 更新数据
    class func keyChainUpdata(data:Any ,withIdentifier identifier:String)->Bool {
        // 获取更新的条件
        let keyChainUpdataMutableDictionary = self.createQuaryMutableDictionary(identifier: identifier)
        // 创建数据存储字典
        let updataMutableDictionary = NSMutableDictionary.init(capacity: 0)
        // 设置数据
        updataMutableDictionary.setValue(NSKeyedArchiver.archivedData(withRootObject: data), forKey: kSecValueData as String)
        // 更新数据
        let updataStatus = SecItemUpdate(keyChainUpdataMutableDictionary, updataMutableDictionary)
        if updataStatus == noErr {
            return true
        }
        return false
    }
    
    
    // TODO: 获取数据
    class func keyChainReadData(identifier:String)-> Any {
        var idObject:Any?
        // 获取查询条件
        let keyChainReadmutableDictionary = self.createQuaryMutableDictionary(identifier: identifier)
        // 提供查询数据的两个必要参数
        keyChainReadmutableDictionary.setValue(kCFBooleanTrue, forKey: kSecReturnData as String)
        keyChainReadmutableDictionary.setValue(kSecMatchLimitOne, forKey: kSecMatchLimit as String)
        // 创建获取数据的引用
        var queryResult: AnyObject?
        // 通过查询是否存储在数据
        let readStatus = withUnsafeMutablePointer(to: &queryResult) { SecItemCopyMatching(keyChainReadmutableDictionary, UnsafeMutablePointer($0))}
        if readStatus == errSecSuccess {
            if let data = queryResult as! NSData? {
                idObject = NSKeyedUnarchiver.unarchiveObject(with: data as Data) as Any
            }
        }
        return idObject as Any
    }
    
    
    
    // TODO: 删除数据
    class func keyChianDelete(identifier:String)->Void{
        // 获取删除的条件
        let keyChainDeleteMutableDictionary = self.createQuaryMutableDictionary(identifier: identifier)
        // 删除数据
        SecItemDelete(keyChainDeleteMutableDictionary)
    }
}

上面展示的代码已经注释非常详细了,就不在多介绍了。如果还有不了解的地方可以查看iOS版本的Keychain,连接如下:iOS的密码管理系统 Keychain的介绍和使用

KeychainManager.swift 类的测试和使用

1、测试代码

// 存储数据
let saveBool = KeychainManager.keyChainSaveData(data: "我期待的女孩" as Any, withIdentifier: KeyChain)
if saveBool {
    print("存储成功")
}else{
    print("存储失败")
}
// 获取数据
let getString = KeychainManager.keyChainReadData(identifier: KeyChain) as! String
print(getString)


// 更新数据
let updataBool = KeychainManager.keyChainUpdata(data: "眼睛像云朵", withIdentifier: KeyChain)
if updataBool {
    print("更新成功")
}else{
    print("更新失败")
}
// 获取更新后的数据
let getUpdataString = KeychainManager.keyChainReadData(identifier: KeyChain) as! String
print(getUpdataString)


// 删除数据
KeychainManager.keyChianDelete(identifier: KeyChain)
// 获取删除后的数据
let getDeleteString = KeychainManager.keyChainReadData(identifier: KeyChain)
print(getDeleteString)

2、测试结果的展示

DAB86C95-248D-45B7-B9B6-D748DB7F9BE1.png

下载Demo 的方法

相关文章

网友评论

本文标题:82-Swift之密码管理(Keychain)的介绍和使用

本文链接:https://www.haomeiwen.com/subject/fknivxtx.html