用于 iOS, macOS, tvOS 和 watchOS 在 Keychain 中存储文本的辅助函数
这是一个用于在 Keychain 中保存文本和数据的辅助函数集合。正如你可能注意到的,Apple 的 Keychain API 有一点冗长。这个库旨在通过提供更短的语法来完成简单的任务:为指定的密钥读取/写入文本值
let keychain = KeychainSwift()
keychain.set("hello world", forKey: "my key")
keychain.get("my key")
Keychain 库包括以下功能
什么是 Keychain?
Keychain 是一个安全存储。您可以在其中存储各种敏感数据:用户密码、信用卡号、密钥令牌等。一旦存储在 Keychain 中,这些信息仅对您的应用程序可用,其他应用程序看不到它。除此之外,操作系统确保这些信息被安全地保留和处理。例如,存储在 Keychain 中的文本无法从 iPhone 备份或其文件系统中提取。Apple 建议只存储少量数据到 Keychain 中。如果您需要保护较大的东西,您可以手动加密,将其保存到文件,并将密钥存储在 Keychain 中。
配置
有四种方法可以将 KeychainSwift 添加到您的项目中。
添加源(iOS 7以上)
简单地将 KeychainSwiftDistrib.swift 文件添加到您的Xcode项目中。
使用Carthage设置(iOS 8以上)
或者,将 github "evgenyneu/keychain-swift" ~> 20.0
添加到您的Cartfile中,然后运行 carthage update
。
使用CocoaPods设置(iOS 8以上)
如果您正在使用CocoaPods,请将以下文本添加到Podfile中,然后运行 pod install
。
use_frameworks!
target 'Your target name'
pod 'KeychainSwift', '~> 20.0'
使用Swift Package Manager设置
- 在Xcode 11+中选择 *文件 > 添加包。
- 输入此项目的URL:https://github.com/evgenyneu/keychain-swift.git
旧版Swift版本
如果您使用的是较旧的Swift版本,请设置库的 旧版本。
用法
除非您使用了文件设置方法,否则请将 import KeychainSwift
添加到您的源代码中。
字符串值
let keychain = KeychainSwift()
keychain.set("hello world", forKey: "my key")
keychain.get("my key")
布尔值
let keychain = KeychainSwift()
keychain.set(true, forKey: "my key")
keychain.getBool("my key")
数据值
let keychain = KeychainSwift()
keychain.set(dataObject, forKey: "my key")
keychain.getData("my key")
从钥匙串中移除密钥
keychain.delete("my key") // Remove single key
keychain.clear() // Delete everything from app's Keychain. Does not work on macOS.
返回所有密钥
let keychain = KeychainSwift()
keychain.allKeys // Returns the names of all keys
高级选项
密钥项访问
使用 withAccess
参数指定钥匙串存储的安全级别。默认使用 .accessibleWhenUnlocked
选项。这是一种最限制性的选项之一,提供了良好的数据保护。
let keychain = KeychainSwift()
keychain.set("Hello world", forKey: "key 1", withAccess: .accessibleWhenUnlocked)
.accessibleAfterFirstUnlock
可用于在后端后台访问密钥项。注意,它比 .accessibleWhenUnlocked
选项的安全性要低。
查看所有可用的 访问选项 列表。
与其他设备同步密钥项
将 synchronizable
属性设置为 true
以启用密钥项在用户的多台设备间同步。只有设备上在设置中启用了 "密钥链" 的用户才能使用同步功能。
将 synchronizable
属性设置为 true
会在其他设备上使用 set
方法添加项,并使用 get
命令获取可同步项。删除同步项将从所有设备中移除。
请注意,您不需要在应用的目标中启用iCloud或密钥链共享功能,该功能才能正常工作。
// First device
let keychain = KeychainSwift()
keychain.synchronizable = true
keychain.set("hello world", forKey: "my key")
// Second device
let keychain = KeychainSwift()
keychain.synchronizable = true
keychain.get("my key") // Returns "hello world"
我们无法在macOS上获取密钥链同步工作。
与其他应用共享密钥项
若要在同一设备上的应用之间共享密钥项,需要在 “功能”>“密钥链共享”>“密钥链组” 设置中注册共同的密钥链组。 本教程 展示了如何设置。
使用 accessGroup
属性来访问共享密钥项。在下面的示例中,我们指定了一个访问组 "CS671JRA62.com.myapp.KeychainGroup",该组将用于设置、获取和删除 "my key" 项。
let keychain = KeychainSwift()
keychain.accessGroup = "CS671JRA62.com.myapp.KeychainGroup" // Use your own access goup
keychain.set("hello world", forKey: "my key")
keychain.get("my key")
keychain.delete("my key")
keychain.clear()
注意:在 watchOS 2.0 和其配对设备之间无法共享密钥项:https://forums.developer.apple.com/thread/5938
设置密钥前缀
在初始化 KeychainSwift
对象时传递一个 keyPrefix
参数。在 keyPrefix
参数中传递的字符串将被用作 set
、get
、getData
和 delete
方法中使用的所有 密钥 的前缀。给密钥链键添加前缀在单元测试中可能很有用。这可以防止在手动启动应用时更改密钥链键。
请注意,clear
方法仍然会清除使用的前缀之外的密钥链中所有内容。
let keychain = KeychainSwift(keyPrefix: "myTestKey_")
keychain.set("hello world", forKey: "hello")
// Value will be stored under "myTestKey_hello" key
检查操作是否成功
可以通过检查 set
,delete
和 clear
方法返回值来验证这些方法是否成功完成。这些方法在成功时返回 true
,在出错时返回 false
。
if keychain.set("hello world", forKey: "my key") {
// Keychain item is saved successfully
} else {
// Report error
}
要获取特定的错误原因,请使用包含最后操作结果的 lastResultCode
属性。请参阅 Keychain 结果代码。
keychain.set("hello world", forKey: "my key")
if keychain.lastResultCode != noErr { /* Report error */ }
以引用的形式返回数据
使用 asReference: true
参数以引用形式返回数据,这对于使用 NEVPNProtocol 是必需的。
let keychain = KeychainSwift()
keychain.set(dataObject, forKey: "my key")
keychain.getData("my key", asReference: true)
从 Objective-C 中使用 KeychainSwift
请参阅本手册了解如何在 Objective-C 应用中使用 KeychainSwift。
❗️ 已知关键问题 - 减少行动❗️
据 报告,该库有时会返回 nil
而不是存储在 Keychain 中的值。这可能与在 Apple 开发者论坛上报告的 Keychain 问题 有关。该问题是随机的,很难重现。如果您遇到该问题,请随时创建一个问题并分享您的经历,以便我们找到解决方案。
视频教程
感谢来自 rebeloper.com 的 Alex Nagy 创建这个两部分的 视频教程。
演示应用
其他解决方案
以下是其他一些键链库。
- DanielTomlinson/Latch
- jrendel/SwiftKeychainWrapper
- kishikawakatsumi/KeychainAccess
- matthewpalmer/Locksmith
- s-aska/KeyClip
- yankodimitrov/SwiftKeychain
👍
感谢- 代码基于以下示例:https://gist.github.com/s-aska/e7ad24175fb7b04f78e7
- 感谢 diogoguimaraes 添加了 Swift 包管理器设置选项。
- 感谢 glyuck 解决了布尔值问题。
- 感谢 pepibumur 添加了对 macOS、watchOS 和 tvOS 的支持。
- 感谢 ezura 添加对 iOS 7 的支持。
- 感谢 mikaoj 添加了密钥同步功能。
- 感谢 tcirwin 添加了对 Swift 3.0 的支持。
- 感谢 Tulleb 添加了对 Xcode 8 测试版的支持。
- 感谢 CraigSiemens 添加了对 Swift 3.1 的支持。
- 感谢 maxkramerbcgdv 解决了 Xcode 8.2 中的包管理器设置问题。
- 感谢 elikohen 解决了并发问题。
- 感谢 beny 添加了对 Swift 4.2 的支持。
- 感谢 xuaninbox 解决了 Xcode 10 中 watchOS 部署目标的问题。
- 感谢 schayes04 添加了对 Swift 5.0 的支持。
- 感谢 mediym41 添加了返回数据引用的能力。
- 感谢 AnthonyOliveri 添加了从 Swift 包管理器运行单元测试的能力。
- 感谢 philippec 移除了已弃用的访问选项。
- 感谢 lucasmpaim 添加了返回所有密钥名称的能力。
欢迎反馈
如果您发现问题、卡住了,或者只是想聊天,请随意创建一个问题。我们将很乐意帮助您。
许可证
Keychain Swift 采用 MIT 许可协议 发布。