用于在 iOS、macOS、tvOS 和 WatchOS 的 Keychain 中存储文本的辅助函数

Carthage compatible CocoaPods Version Swift Package Manager compatible License Platform

这是一个用于在 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" ~> 24.0 添加到您的 Cartfile 文件,然后运行 carthage update

使用 CocoaPods 设置 (iOS 8+)

如果您正在使用 CocoaPods,请将此文本添加到您的 Podfile 文件,然后运行 pod install

use_frameworks!
target 'Your target name'
pod 'KeychainSwift', '~> 24.0'

使用 Swift Package Manager 设置(在项目中)

使用 Swift Package Manager 设置(在 Swift 包中)

如果您在 Swift 包中使用 KeychainSwift,请务必指定一个 name。这是因为 SPM 无法自动解析具有不同 Target 名称(即 KeychainSwift)的包的名称,该名称与其 Package.swift 中的 repo 链接(keychain-swift)不同。

.package(name: "KeychainSwift", url: "https://github.com/evgenyneu/keychain-swift.git", from: "24.0.0")

旧版 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 中移除键

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

高级选项

Keychain 项访问

使用 withAccess 参数来指定 keychain 存储的安全级别。默认情况下,使用 .accessibleWhenUnlocked 选项。 它是最具限制性的选项之一,并提供良好的数据保护。

let keychain = KeychainSwift()
keychain.set("Hello world", forKey: "key 1", withAccess: .accessibleWhenUnlocked)

如果您需要您的应用在后台访问 keychain 项,您可以使用 .accessibleAfterFirstUnlock。 请注意,它不如 .accessibleWhenUnlocked 选项安全。

查看所有可用访问选项的列表。

与其他设备同步 keychain 项

synchronizable 属性设置为 true 以启用 keychain 项在用户多个设备之间的同步。 对于在其设备的 iCloud 设置中启用了“Keychain”的用户,该同步将起作用。

synchronizable 属性设置为 true 会将项目通过 set 方法添加到其他设备,并通过 get 命令获取可同步的项目。 删除可同步的项目将从所有设备中删除它。

请注意,您不需要在您应用的目标中启用 iCloud 或 Keychain Sharing 功能才能使此功能生效。

// 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 上使 Keychain 同步工作。

与其他应用共享 keychain 项

为了在同一设备上的应用之间共享 keychain 项,它们需要在 *Capabilities > Keychain Sharing* 设置中注册通用的 *Keychain Groups*。本教程演示了如何设置它。

使用 accessGroup 属性来访问共享的 keychain 项。 在以下示例中,我们指定了一个访问组“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 和其配对设备之间共享 keychain 项:https://forums.developer.apple.com/thread/5938

设置键前缀

可以在初始化 KeychainSwift 对象时传递 keyPrefix 参数。 传递给 keyPrefix 参数的字符串将用作 setgetgetDatadelete 方法中使用的所有键的前缀。 在单元测试中,向 keychain 键添加前缀很有用。 这可以防止测试更改手动启动应用时使用的 Keychain 键。

请注意,无论使用什么前缀,clear 方法仍然会清除 Keychain 中的所有内容。

let keychain = KeychainSwift(keyPrefix: "myTestKey_")
keychain.set("hello world", forKey: "hello")
// Value will be stored under "myTestKey_hello" key

检查操作是否成功

可以通过检查 setdeleteclear 方法的返回值来验证它们是否已成功完成。 这些方法在成功时返回 true,在出错时返回 false

if keychain.set("hello world", forKey: "my key") {
  // Keychain item is saved successfully
} else {
  // Report error
}

要获取特定的失败原因,请使用包含上次操作结果代码的 lastResultCode 属性。 请参阅Keychain Result Codes

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 创建了这个分为两部分的视频教程

Keychain Swift video tutorial

演示应用

Keychain Swift demo app

替代解决方案

以下是一些其他的 Keychain 库。

感谢 👍

欢迎提供反馈

如果您发现任何问题、遇到困难或只是想聊天,请随时创建一个 issue。 我们将很乐意为您提供帮助。

许可证

Keychain Swift 在 MIT 许可证下发布。