Highlight
iOS 15 和 macOS Monterey 将 TOTP 验证码生成器内置到 iCloud Keychain 密码管理器中,支持一键设置、AutoFill 自动填充、跨设备同步和安全备份,让多因素认证比 SMS 更安全、更便宜、更可靠。
核心内容
密码的问题
密码是互联网上最普遍的认证方式,但人并不擅长正确使用密码。很多人会重复使用密码,或者选择容易猜测的密码。攻击者也很容易通过钓鱼手段骗取密码。
为了增强安全性,许多服务在登录流程中增加了额外的步骤——验证码(Verification Code)。用户在输入用户名和密码后,还需要输入一个一次性代码来确认身份。
SMS 验证码的隐患
目前最常见的验证码传递方式是 SMS。虽然 AutoFill 让输入 SMS 验证码变得很方便(一键填充),但 SMS 存在几个严重问题:
- 安全性差:SMS 容易被运营商网络嗅探,也面临 SIM 卡交换攻击的风险
- 依赖网络:在飞机上或信号弱的地方,短信可能延迟很久甚至收不到
- 成本高:对服务方来说,发送数百万条短信是一笔不小的开销
TOTP:设备本地生成验证码
TOTP(Time-Based One-Time Password)基于 RFC 6238 标准,通过秘密密钥和时间戳在设备本地生成短数字代码。这种方式不需要与服务端通信,安全性更高,也没有 SMS 的费用。
但 TOTP 的设置过程一直比较繁琐:用户需要在一个设备上显示二维码,在另一个设备上下载认证器 App,然后扫描二维码。这个过程对普通用户来说很难理解。
iCloud Keychain 内置验证码生成器
iOS 15 和 macOS Monterey 将 TOTP 验证码生成器直接内置到 iCloud Keychain 密码管理器中,解决了上述所有痛点:
- 一键设置:在 TOTP 设置页面添加特殊链接,用户只需两次点击即可完成设置
- AutoFill 自动填充:与 SMS 验证码一样,生成的验证码可以一键自动填充到输入框
- 跨设备同步:验证码通过 iCloud Keychain 在所有设备间同步,在 Mac 上登录不需要掏出 iPhone
- 安全备份:验证码安全备份在 iCloud 中,丢失设备不会丢失账户访问权限
- 端到端加密:iCloud Keychain 中的所有数据都是端到端加密的,Apple 也无法访问
详细内容
如何支持一键设置
(08:06)要让用户能够轻松设置验证码,需要在 TOTP 设置页面添加一个链接或按钮。
TOTP 设置通常使用 otpauth:// URL,包含 base32 编码的秘密密钥、验证码位数、有效期和 issuer 字段。iCloud Keychain 使用 issuer 字段来建议将验证码添加到哪个账户。
要直接链接到 iCloud Keychain 密码管理器,只需在 URL 前加上 apple- 前缀:
// 在 App 中,通过按钮点击打开设置 URL
func openVerificationCodeSetup(url: URL) {
if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
scene.open(url, options: nil, completionHandler: nil)
}
}
// 在网页中,使用锚标签
// <a href="apple-otpauth://totp/Example?secret=...&issuer=example.com">设置验证码</a>
关键点:
otpauth://URL 包含设置验证码生成器所需的所有信息- 加上
apple-前缀后,系统会直接打开 iCloud Keychain 密码管理器 - 在 iOS 上,可以通过
UIWindowScene的openAPI 打开这个 URL - 在网页中,可以直接用锚标签链接
- 需要通过可用性检查(availability check)确认系统支持
apple-otpauth://URL,旧版本系统应隐藏设置按钮
QR 码的 Safari 集成
(10:02)如果使用 JPG、PNG 或 GIF 格式的 QR 码图片,Safari 会通过设备端图像分析检测 QR 码。如果 Safari 判断 QR 码包含 otpauth:// URL,会在 QR 码图片的上下文菜单中提供设置验证码生成器的选项。
文本字段的 content type 标注
(10:30)为了让 AutoFill 知道在哪里填充用户名、密码和验证码,需要为文本字段标注 content type。
在 SwiftUI 中:
TextField("Verification Code", text: $code)
.textContentType(.oneTimeCode)
在 UIKit 中:
let textField = UITextField()
textField.textContentType = .oneTimeCode
在网页中:
<input type="text" autocomplete="one-time-code" />
关键点:
.oneTimeCodecontent type 告诉系统这是一个验证码输入框- 标注后,AutoFill 会自动提供从 SMS 或 TOTP 生成器获取的验证码
- 网页上使用
autocomplete="one-time-code"属性
SMS 验证码的域名绑定
(13:11)如果仍然需要使用 SMS 验证码,iOS 14 和 macOS Big Sur 引入了域名绑定(domain binding)机制来增强安全性。
在 SMS 消息中添加域名绑定信息,告诉 AutoFill 这个验证码是给特定域名的。当域名匹配时,AutoFill 才会提供验证码。这可以防止钓鱼网站获取用户的 SMS 验证码。
域名绑定使用与 Universal Links 相同的 associated domains 机制。如果 App 已经配置了 associated domains,就可以直接添加域名绑定支持。
核心启发
-
替换 SMS 验证码:在 App 和网站的后端支持 TOTP,引导用户从 SMS 切换到设备本地生成的验证码。这能降低成本、提升安全性,并改善无网络环境下的用户体验。入口是从服务端生成
otpauth://URL。 -
一键设置流程:在用户开启两步验证的设置页面,添加 “在 iCloud Keychain 中设置” 按钮。使用
apple-otpauth://URL 前缀,让用户在 iOS 15+ 设备上只需两次点击即可完成设置,省去扫描二维码的繁琐步骤。 -
增强 SMS 安全:如果暂时无法完全放弃 SMS 验证码,立即为 SMS 消息添加域名绑定。这能防止钓鱼攻击窃取验证码,且配置成本很低——复用已有的 associated domains 设置即可。
-
统一认证体验:将
textContentType(.oneTimeCode)应用到所有验证码输入框。这样无论验证码来自 SMS 还是 TOTP 生成器,用户都能获得一致的一键填充体验。
关联 Session
- Move beyond passwords — WebAuthn 技术预览和 passkeys 介绍,密码的终极替代方案
- Meet Face ID and Touch ID for the web — Web 端生物识别认证
- What’s new in Sign in with Apple — 联邦认证和 Sign in with Apple 更新
评论
GitHub Issues · utterances