0Pricing
Swift Academy · 课时

钥匙串访问控制

通过生物识别和设备解锁保护项目。

钥匙串访问控制 是 CoddyKit 上的免费 Swift Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Swift Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Swift Academy 课程共包含 4 节课。

控制何时可以读取机密数据

存储机密数据只是完成了一半的工作——您还必须控制它在何时可以被读取。钥匙串提供了可访问性类别和访问控制标志,可以要求项目必须在设备解锁、输入密码或通过生物识别后才能访问。如果设备丢失,这些机制可以保护数据。

import Security
// Two layers of control:
//   kSecAttrAccessible  -> when readable (lock state)
//   SecAccessControl    -> user presence / biometrics

kSecAttrAccessible 属性键

kSecAttrAccessible 会在添加项目时设置其可访问性类别。它决定项目是始终可用、仅在首次解锁后可用,还是仅在设备处于解锁状态时可用。请选择功能允许的最严格级别。

import Security
let query: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrAccount as String: "user",
    kSecValueData as String: Data("secret".utf8),
    kSecAttrAccessible as String:
        kSecAttrAccessibleWhenUnlocked
]
_ = query

WhenUnlocked

kSecAttrAccessibleWhenUnlocked 使项目仅在设备解锁期间可读。设备锁定时运行的后台任务无法访问它。对于大多数会话令牌,这是合理的默认设置。

import Security
// Readable only while unlocked; blocked when locked.
let level = kSecAttrAccessibleWhenUnlocked
_ = level

AfterFirstUnlock

kSecAttrAccessibleAfterFirstUnlock 会使项目从设备启动后的首次解锁开始保持可读,直到下一次重启为止——即使之后设备再次锁定,项目仍然可读。对于后台进程所需的机密数据(例如处理推送所需的令牌),可以使用它。

import Security
// Available after the first unlock post-boot,
// including while subsequently locked.
let level = kSecAttrAccessibleAfterFirstUnlock
_ = level

ThisDeviceOnly 变体

每个可访问性类别都有一个 ...ThisDeviceOnly 形式。这些项目不会包含在加密备份中,也不会迁移到新设备。对于绝不应离开当前硬件的密钥,请使用这些形式。

import Security
// Never backed up, never migrated:
let local = kSecAttrAccessibleWhenUnlockedThisDeviceOnly
_ = local

设置密码时

kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly 仅在用户设置了密码时存储项目;如果用户移除密码,该项目也会被删除。它可以保证机密数据始终受到密码保护。

import Security
let level =
    kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
// Item vanishes if the user disables their passcode.
_ = level

使用 SecAccessControl 要求用户在场

除了锁定状态之外,SecAccessControlCreateWithFlags 还可以构建一个策略,要求用户在读取时主动进行身份验证——使用生物识别或密码。您可以通过 kSecAttrAccessControl 附加该策略,以替代可访问性属性或与其同时使用。

import Security
func makeControl() -> SecAccessControl? {
    return SecAccessControlCreateWithFlags(
        nil,
        kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
        .userPresence,
        nil)
}

访问控制标志

标志可以进一步细化要求:.userPresence 允许使用生物识别或密码回退;.biometryCurrentSet 会在已录入的指纹或面容发生变化时使项目失效;.devicePasscode 会强制要求输入设备密码。您可以组合使用它们来表达安全需求。

import Security
// .userPresence        -> biometric OR passcode
// .biometryAny         -> any enrolled biometric
// .biometryCurrentSet  -> invalidate on biometric change
// .devicePasscode      -> passcode only
let flags: SecAccessControlCreateFlags = [.userPresence]
_ = flags

添加受保护的项目

要存储受生物识别保护的机密数据,请将 SecAccessControl 对象放在 kSecAttrAccessControl 下。之后的任何读取都会先提示用户进行身份验证,然后才返回数据。

import Security
func saveProtected(_ data: Data, account: String,
                   control: SecAccessControl) -> Bool {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: account,
        kSecValueData as String: data,
        kSecAttrAccessControl as String: control]
    return SecItemAdd(query as CFDictionary, nil)
        == errSecSuccess
}

读取时提示用户

读取受保护的项目会自动触发身份验证界面。您可以通过 kSecUseOperationPrompt 提供原因字符串,让提示说明为什么需要访问。读取操作会一直阻塞,直到用户完成身份验证或取消操作。

import Security
func readProtected(account: String) -> Data? {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: account,
        kSecReturnData as String: true,
        kSecUseOperationPrompt as String:
            String(localized: "Unlock your saved key")]
    var out: CFTypeRef?
    return SecItemCopyMatching(query as CFDictionary,
        &out) == errSecSuccess ? out as? Data : nil
}

选择合适的级别

请根据风险匹配策略:

  • 后台使用的会话令牌:AfterFirstUnlock。
  • 仅用户界面使用的令牌:WhenUnlocked。
  • 高价值机密数据:使用带有 .userPresence 的 SecAccessControl,以及 ThisDeviceOnly 类别。

更严格的设置更安全,但会中断后台访问——请在两者之间取得平衡。

import Security
// High-value: biometric-gated, device-bound, no backup
let control = SecAccessControlCreateWithFlags(
    nil,
    kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
    .userPresence, nil)
_ = control

快速检查

请回忆一下,哪种可访问性类别适合后台所需的机密数据。

回顾

您已经学习了如何限制钥匙串项目的访问:

  • kSecAttrAccessible 设置项目在不同锁定状态下的可用性:WhenUnlocked、AfterFirstUnlock,以及不会使用备份的 ...ThisDeviceOnly 变体。
  • WhenPasscodeSetThisDeviceOnly 将项目与设备是否设置密码关联起来。
  • 带有 .userPresence 或 .biometryCurrentSet 等标志的 SecAccessControl 会要求在读取时进行身份验证。
  • 请选择在满足访问模式的前提下最严格的级别。

常见问题解答

「钥匙串访问控制」课时是免费的吗?

是的 — 「钥匙串访问控制」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Swift Academy 课程的其余内容,请升级到 CoddyKit PRO。 Swift Academy 课程共包含 4 节课。

「钥匙串访问控制」这节课中我会学到什么?

通过生物识别和设备解锁保护项目。 你通过在浏览器中直接运行的动手代码来练习 Swift Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Swift Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Swift Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「钥匙串访问控制」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Swift Academy 课中编写并运行代码吗?

能。每节 Swift Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 在钥匙串中存储机密
  2. 钥匙串访问控制
  3. 生物识别身份验证
  4. 数据保护与加密
← 返回 Swift Academy