iOS 的 keychain 服務提供了一種安全的保存私密信息(密碼,序列號,證書等)的方式,每一個ios程序都有一個獨立的keychain存儲。
用於儲存一些私密信息,好比密碼、證書等等,Keychain裏保存的信息不會因App被刪除而丟失,在用戶從新安裝App後依然有效。
一樣也適用於應用之間數據共享。咱們能夠把KeyChain理解爲一個Dictionary,全部數據都以key-value的形式存儲,能夠對這個Dictionary進行add、update、get、delete這四個操做。ios
OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef * __nullable CF_RETURNS_RETAINED result)
複製代碼
attributes: 要添加的數據
result: 存儲數據後,返回一個指向該數據的引用,不使用該數據傳入 nilswift
OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef * __nullable CF_RETURNS_RETAINED result)
複製代碼
query: 要查詢數據的條件
result: 查詢到數據的引用安全
OSStatus SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate)
複製代碼
query: 要更新數據的查詢條件
attributesToUpdate: 要更新的數據bash
OSStatus SecItemDelete(CFDictionaryRef query)
複製代碼
query: 要刪除數據的查詢條件app
使用 Keychain 首先須要導入安全框架 secutity.framework框架
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
}
複製代碼
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
}
複製代碼
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
}
複製代碼
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
}
複製代碼
class func keyChianDelete(identifier: String)->Void{
// 獲取刪除的條件
let keyChainDeleteMutableDictionary = self.createQuaryMutableDictionary(identifier: identifier)
// 刪除數據
SecItemDelete(keyChainDeleteMutableDictionary)
}
複製代碼
直接獲取 UUID 每次卸載從新安裝 app 後可能會致使 UUID 變化,爲了獲取惟一的 UUID,咱們使用 keyChian 對 UUID 進行保存ide
class func getUUID() -> String {
if let uuid = QWUUIDTools.keyChainReadData(identifier: "key") as? String {
return uuid
}else {
if let uuid = UIDevice.current.identifierForVendor?.uuidString {
if QWUUIDTools.keyChainSaveData(data: uuid, withIdentifier: "key") {
return uuid
}
}
}
return "simulator"
}
複製代碼