导入库
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)
}
}
网友评论