swift之保存数据到keychain

访问KeyChain

1.在mac上按下 Command+Space 输入Keychain Access

2.在终端输入security find-generic-password -help

读取配置文件授权

cd ~/Desktop

//ios产看应用的授权来发现他需要的访问类型,应用的授权以编码的形式保存在对应的签名的配置文件中,嘉定已经创建一个配置文件,名为KeycahinTest_Dev.mobileprovision并且保存在桌面

security cms -D -i KeychainTest_Dev.mobileprovision | grep -A12 “Entitlements” 

 

 

keychain-acess-groups 定义同一开发者开发的应用所共享的钥匙串群组标识

 

ios应用中使用key-chain

1.引入框架 import Security    修改Build Setting中Capabilities支持

 

使用Touch ID验证用户

 

1.引入LocalAuthentication框架

2.创建LAContext类的实例

3.调用LAContext实例的canEvaluatePolicy:(LAPolicyDeviceOwnerAuthenticaitonWithBiometrics)error:方法确认Touch Id是否可用

 

4.Touchid可用则使用LAContext的evaluatePolicy:localizedReason:reply:方法验证TouchID的用户

 

import UIKit

import LocalAuthentication

 

class ViewController: UIViewController {

    

    @IBOutlet weak var buttonCheckTouchId: UIButton!

    

    @IBOutlet weak var buttonUseTouchId: UIButton!

    

    override func viewDidLoad() {

        super.viewDidLoad()

        

       

    }

 

    //touchId是否可用

    func checkTouchIdAvailability(sender: AnyObject) {

        let context = LAContext()

        var error: NSError?

        let isTouchIdAvailable = context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)

        buttonUseTouchId.isEnabled = isTouchIdAvailable

        //Touch ID不可用的

        if isTouchIdAvailable == false {

            let alertController = UIAlertController(title: "Touch Id", message: "TocuhId is not available", preferredStyle: .alert)

            alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))

            present(alertController, animated: true, completion: nil)

        }

        

    }

    @IBAction func userTouchId(sender: AnyObject) {

        let context = LAContext()

        var error: NSError?

        //localizedReason标识在应用中请求用户提供指纹进行验证的文本提示内容

        let reason = "please authenticate with Touch id to access your private information"

        context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason, reply: { (success: Bool, error: NSError!) in

            if success{

                //用户已经通过验证

            }else{

                //用户为通过验证

            }

            } as! (Bool, Error?) -> Void)

        

    }

 

}

 

 

 

 

 

在钥匙串中存储数据是以键值对方式存储的

kSecCalss    安全存储字符串数据

kSecClassGenericPassword

kSecAttrService  应用bundle标识字符窜

kSecAttrAcount   存储数据的对应键,可以是任意有意义的字符串

kSecValueData 该键的值是一个NSData实例,存放kSecAttrAccount对应的数据

 

OSStatus类型在xcode中Commond+ shilft + O 输入SecBase 查找errSecSucces,可以看到OSStatus类型

 

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        // Override point for customization after application launch.

       

        return true

    }

    //保存到钥匙串

    func savetoKeyChain() {

        let key = "Full Name"

        let value = "Steve Jobs"

        let valueData = value.data(using: .utf8, allowLossyConversion: false)

        let service = Bundle.main.bundleIdentifier!

        let secItem = [

            kSecClass as NSString : kSecClassGenericPassword as NSString,

            kSecAttrService as NSString : service,

            kSecAttrAccount as NSString : key,

            kSecValueData as NSString : valueData!

            ] as NSDictionary

        

        var result:CFTypeRef?

        let status = Int(SecItemAdd(secItem, &result))

        switch status {

        case Int(errSecSuccess):

            print("Successfully stored the value")

        case Int(errSecDuplicateItem):

            print("this item is already saved, Cannot duplicate it")

        default:

            print("An error occurred with code\(status)")

        }

    }

    //在钥匙串中查找数据

    /****查找钥匙串h中的值

     SecItemCopyMatching(CFDictionary, UnsafeMutablePointer<CFTypeRef?>?)

     1.构建一个字典,天剑kSecClass键,设置键的值来标识查找项的类型。 例如:kSecClassGenericPassword

     2.添加kSecAttrService键。取值为查找项服务的字符串,所有应用应采用相同的值,这样任意应用写到钥匙串的数据,其他应用可以访问

     3.添加kSecAttrAccount键,取值为钥匙串已存储项对应的键

     4.获取特定属性的值:创建修改日期,需要向字典中添加kSecReturnAttributes,并将其值设置为kCFBooleanTrue

     

     如果设置CFDictionary键为 kSecReturnAttributes键,则返回值为nil或CFDictionaryRef隐含类型

     如果为kSecReturnData添加到字典,返回类型是CDDataRef

     **/

    func queryFromKeyChain(){

        let keyToSearchfor = "Full Name"

        let service = Bundle.main.bundleIdentifier

        let query = [kSecClass as NSString : kSecClassGenericPassword as NSString,

                     kSecAttrAccount as NSString : keyToSearchfor,

                     kSecAttrService as NSString : service,

                     kSecReturnAttributes as NSString : kCFBooleanTrue

            ] as NSDictionary

        var valueAttributes : CFTypeRef?

        let results = Int(SecItemCopyMatching(query, &valueAttributes))

        if results == Int(errSecSuccess) {

            let attributes = valueAttributes! as! NSDictionary

            let key = attributes[kSecAttrAccount as NSString] as! String

            let accessGroup = attributes[kSecAttrAccessGroup as NSString] as! String

            let createDate = attributes[kSecAttrCreationDate as NSString] as! NSDate

            let modifiedDate = attributes[kSecAttrModificationDate as NSString] as! NSDate

            let serviceValue = attributes[kSecAttrService as NSString] as! String

            

        }else{

            print("Error happened with code:\(results)")

        }

        

    }

    func queryDataFromKeyChain(){

        let keyToSearchfor = "Full Name"

        let service = Bundle.main.bundleIdentifier

        let query = [kSecClass as NSString : kSecClassGenericPassword as NSString,

                     kSecAttrAccount as NSString : keyToSearchfor,

                     kSecAttrService as NSString : service,

                     kSecReturnData as NSString : kCFBooleanTrue

            ] as NSDictionary

        var returnedData : CFTypeRef?

        let results = Int(SecItemCopyMatching(query, &returnedData))

        if results == Int(errSecSuccess) {

            let data = returnedData! as! Data

            let value = String(data: data, encoding: .utf8)

            

            

        }else{

            print("Error happened with code:\(results)")

        }

        

    }

    func updateKeyChain() {

        let keyToSearchFor = "Full Name"

        let service = Bundle.main.bundleIdentifier

        let query = [kSecClass as NSString:

                     kSecClassGenericPassword as NSString,

                     kSecAttrService as NSString: service,

                     kSecAttrAccount as NSString : keyToSearchFor,] as NSDictionary

        var result: CFTypeRef?

        let found = Int(SecItemCopyMatching(query, &result))

        if found == Int(errSecSuccess){

            let newData = "Mark tremonti".data(using: .utf8, allowLossyConversion: false)

            let update = [kSecValueData as NSString: newData!,

                          kSecAttrComment as NSString : "my comments"] as NSDictionary

            let updated = Int(SecItemUpdate(query, update))

            if updated == Int(errSecSuccess){

                print("Successfully updated the existing value")

                readExistingValue();

            } else {

                print("failed to update the value. error = \(updated)")

            }

        }else{

            print("error happened. Code=\(found)")

        }

        

    }

    //更新多个值

    func readExistingValue() {

        

        

    }

 

posted @ 2019-02-11 16:53  sundayswift  阅读(1745)  评论(0编辑  收藏  举报