钥匙串uuid存储服务创建、获取

2019-10-08  本文已影响0人  微凉初夏

导入库

import Security

创建管理单例

final class KeyChainManager {

static let share = KeyChainManager()

//////************************************************💕调用方法💕*******************************************************//////

public func saveUUID(_ uuid: String) {
    self.save(uuid, key_uuid)
}

public func readUUID() -> String {
    if value_uuid.count > 0 {
        return value_uuid
    }
    
    let uuid = self.load(service: key_uuid)
    
    if uuid.count == 0 {
        let _uuid = EDevice.getUUID()
        self.saveUUID(_uuid)
        value_uuid = _uuid
        
        return _uuid
    }
    
    value_uuid = uuid
    
    return uuid
}

public func deleteUUid() {
    self.deleteKeyData(service: key_uuid)
}

//////*************************************************💕值💕*************************************************//////

//// key
private let key_uuid = "com.yourServiceName.keychain"

//// value
private var value_uuid = ""

//////************************************************💕基础方法💕*****************************************************//////

/*
 kSecAttrGeneric  标识符(此属性是可选项,但是为了能获取存取的值更精确,最好还是写上吧)
 kSecClass  是你存数据是什么格式,这里是通用密码格式
 kSecAttrService  存的是什么服务,这个是用来到时候取的时候找到对应的服务存的值(这个属性类似于主键,kSecAttrService、kSecAttrAccount必须要赋一个值)
 kSecAttrAccount  账号,在这里作用与服务没差别(且是否必写与kSecAttrService一样)
 当你有服务或者账号则必须有密码
 kSecAttrAccessible  安全性
 */
private func getKeychainQuery(service: String) -> NSMutableDictionary {
    return NSMutableDictionary(objects: [kSecClassGenericPassword, "com.yourServiceName", service, service, kSecAttrAccessibleAlways], forKeys: [kSecClass as! NSCopying, kSecAttrGeneric as! NSCopying, kSecAttrService as! NSCopying, kSecAttrAccount as! NSCopying, kSecAttrAccessible as! NSCopying])
}

private func save(_ data: Any, _ service: String) {
    // Get search dictionary
    let keychainQuery = self.getKeychainQuery(service: service)
    // Delete old item before add new item
    SecItemDelete(keychainQuery)
    // Add new object to search dictionary(Attention:the data format)
    do {
        var data = Data()
        if #available(iOS 11.0, *) {
            data = try NSKeyedArchiver.archivedData(withRootObject: data, requiringSecureCoding: true)
        } else {
            data = NSKeyedArchiver.archivedData(withRootObject: data)
        }
        keychainQuery.setObject(data, forKey: kSecValueData as! NSCopying)
        // Add item to keychain with the search dictionary
        SecItemAdd(keychainQuery, nil)
    }catch {
        deprint("钥匙串存储报错:" + error.localizedDescription)
    }
}

/// 加载
private func load(service: String) -> String {
    var ret: String = ""
    let keychainQuery = self.getKeychainQuery(service: service)
    // Configure the search setting
    // Since in our simple case we are expecting only a single attribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue
    keychainQuery.setObject(kCFBooleanTrue!, forKey: kSecReturnData as! NSCopying)
    keychainQuery.setObject(kSecMatchLimitOne, forKey: kSecMatchLimit as! NSCopying)
    var keyData: CFTypeRef?
    if SecItemCopyMatching(keychainQuery, &keyData) == noErr {
        if let data = keyData as? Data, let r = NSKeyedUnarchiver.unarchiveObject(with: data) as? String {
            ret = r
        }
    }
    return ret
}

/// 删除
private func deleteKeyData(service: String) {
    let keychainQuery = self.getKeychainQuery(service: service)
    SecItemDelete(keychainQuery)
}

}
上一篇 下一篇

猜你喜欢

热点阅读