在 Swift 中使用钥匙串读取和保存密码
Keychain 是适用于 macOS 和 iOS 的安全存储接口,最适合用于存储小块私人数据,例如密码、cookie 和身份验证令牌。
SecItemAdd 将数据保存到钥匙串
func SecItemAdd(_ attributes: CFDictionary, _ result: UnsafeMutablePointer<CFTypeRef?>?) -> OSStatus
SecItemAdd 用于将新项目保存到 Keychain。
-
kSecAttrService
一个字符串,用于标识一组钥匙串项目,如 com.my-app.bundle-id -
kSetAttrAccount
一个字符串,用于标识特定服务中的钥匙串项,例如 username`@email.com -
kSecClass
一种存储在 Keychain Item 中的安全数据,例如 kSecClassGenericPassword
第二个参数 result
是 UnsafeMutablePointer 查询指定的任何返回值。通常不需要返回数据,并且nil可以传递结果。
static func save(password: Data, service: String, account: String) -> Bool {
let query: [String: AnyObject] = [
// kSecAttrService, kSecAttrAccount, and kSecClass
// uniquely identify the item to save in Keychain
kSecAttrService as String: service as AnyObject,
kSecAttrAccount as String: account as AnyObject,
kSecClass as String: kSecClassGenericPassword,
// kSecValueData is the item value to save
kSecValueData as String: password as AnyObject
]
// SecItemAdd attempts to add the item identified by
// the query to keychain
let status = SecItemAdd(query as CFDictionary, nil)
// Any status other than errSecSuccess indicates the
// save operation failed.
return status == errSecSuccess
}
SecItemUpdate 更新钥匙串中的数据
func SecItemUpdate(_ query: CFDictionary, _ attributesToUpdate: CFDictionary) -> OSStatus
SecItemUpdate
用于覆盖 Keychain 中的现有 kSecValueData
数据。
static func update(password: Data, service: String, account: String) -> Bool {
let query: [String: AnyObject] = [
// kSecAttrService, kSecAttrAccount, and kSecClass
// uniquely identify the item to update in Keychain
kSecAttrService as String: service as AnyObject,
kSecAttrAccount as String: account as AnyObject,
kSecClass as String: kSecClassGenericPassword
]
// attributes is passed to SecItemUpdate with
// kSecValueData as the updated item value
let attributes: [String: AnyObject] = [
kSecValueData as String: password as AnyObject
]
// SecItemUpdate attempts to update the item identified
// by query, overriding the previous value
let status = SecItemUpdate(
query as CFDictionary,
attributes as CFDictionary
)
// Any status other than errSecSuccess indicates the
// update operation failed.
return status == errSecSuccess
}
SecItemCopyMatching 从钥匙串中读取数据
func SecItemCopyMatching(_ query: CFDictionary, _ result: UnsafeMutablePointer<CFTypeRef?>?) -> OSStatus
就像 SecItemAdd ,SecItemCopyMatching 方法有一个 UnsafeMutablePointer 参数和一个 query 参数。读取的数据 SecItemCopyMatching 将被复制到 UnsafeMutablePointer result 供 macOS 和 iOS 应用程序访问。
static func readPassword(service: String, account: String) -> Data? {
let query: [String: AnyObject] = [
// kSecAttrService, kSecAttrAccount, and kSecClass
// uniquely identify the item to read in Keychain
kSecAttrService as String: service as AnyObject,
kSecAttrAccount as String: account as AnyObject,
kSecClass as String: kSecClassGenericPassword,
// kSecMatchLimitOne indicates keychain should read
// only the most recent item matching this query
kSecMatchLimit as String: kSecMatchLimitOne,
// kSecReturnData is set to kCFBooleanTrue in order
// to retrieve the data for the item
kSecReturnData as String: kCFBooleanTrue
]
// SecItemCopyMatching will attempt to copy the item
// identified by query to the reference itemCopy
var itemCopy: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &itemCopy)
// Any status other than errSecSuccess indicates the
// read operation failed.
guard status == errSecSuccess else {
return nil
}
// This implementation of KeychainInterface requires all
// items to be saved and read as Data. Otherwise,
// invalidItemFormat is thrown
guard let password = itemCopy as? Data else {
throw nil
}
return password
}
SecItemDelete 删除钥匙串中的数据
func SecItemDelete(_ query: CFDictionary) -> OSStatus
static func deletePassword(service: String, account: String) -> Bool {
let query: [String: AnyObject] = [
// kSecAttrService, kSecAttrAccount, and kSecClass
// uniquely identify the item to delete in Keychain
kSecAttrService as String: service as AnyObject,
kSecAttrAccount as String: account as AnyObject,
kSecClass as String: kSecClassGenericPassword
]
// SecItemDelete attempts to perform a delete operation
// for the item identified by query. The status indicates
// if the operation succeeded or failed.
let status = SecItemDelete(query as CFDictionary)
// Any status other than errSecSuccess indicates the
// delete operation failed.
return status == errSecSuccess
}
与 iCloud 同步钥匙串
如果启用了 iCloud 钥匙串同步,则可以自动将用户的钥匙串数据与该用户的 iCloud 同步。为此,请在为所有钥匙串操作构造钥匙串服务查询时设置 kSecAttrSynchronizable
为 kCFBooleanTrue
query[kSecAttrSynchronizable as String] = kCFBooleanTrue
网友评论