题干与适用场景
SaaS 已有密码登录,计划增加 Passkey。用户可能在手机、笔记本和硬件安全密钥上登录;部分凭据可由平台同步,企业高风险操作要求更强的用户验证。请设计注册、认证、账户恢复、迁移和观测方案。
题目范围是 WebAuthn 与服务端验证边界。Passkey 不自动解决会话管理、账号恢复、设备撤销或业务授权。
面试官考察点
面试官会检查你是否理解:浏览器和认证器持有私钥,服务端保存公钥;每次认证使用一次性随机 challenge;验证器必须检查 challenge、RP ID、origin、签名和所需的用户存在/用户验证标志。
优秀回答还会区分“抗钓鱼”与“永不丢失”:同步凭据改善可用性,却可能不满足最高等级的不可导出要求。恢复流程若绕过同等强度的证明,整套方案仍会被最弱路径击穿。
回答前需要澄清的问题
- 哪些操作只需要登录,哪些操作必须满足 UV 或设备绑定?
- RP ID 是否覆盖多个子域名?是否会在跨来源 iframe 中调用?
- 企业是否禁止可同步凭据,或只允许硬件密钥?
- 账户恢复需要保留哪些现有因素,人工审核能否介入?
- 旧密码、TOTP 和 Passkey 的迁移顺序及撤销期限是什么?
30 秒回答框架
“服务端为每次注册或登录生成一次性 challenge 并绑定会话,认证后校验 RP ID、origin、challenge、签名和所需 UP/UV 标志。注册时只保存公钥、credential ID、计数器和策略元数据,不保存私钥。对同步凭据按风险分级;高风险操作要求 UV 或设备绑定。恢复要使用已有强因素、短时一次性流程和风控审查,不能把短信作为无条件后门。”
分步骤深入解答
第一步:定义注册与认证数据
注册前由服务端生成不可预测、短时有效且只使用一次的 challenge,保存到会话或一次性存储。客户端调用 navigator.credentials.create(),认证器生成密钥对并返回公钥凭据。
服务端保存 credential ID、公钥、所属账号、RP ID、签名计数器、备份资格与备份状态等必要元数据。私钥始终留在认证器或平台凭据管理器中。
第二步:执行严格的认证校验
登录时服务端生成新 challenge 和 publicKeyCredentialRequestOptions,客户端调用 navigator.credentials.get()。收到 assertion 后,验证:
const valid = await verifyAuthenticationResponse({
response,
expectedChallenge: session.challenge,
expectedOrigin: "https://app.example.com",
expectedRPID: "app.example.com",
requireUserVerification: true
});验证成功后立即消费 challenge,拒绝重复使用、过期或跨会话响应,再根据公钥验证签名。验证器还要处理用户取消、浏览器不支持和认证器暂时不可用。
第三步:理解 RP ID、origin 与跨来源风险
RP ID 标识凭据所属的依赖方;凭据不能拿去给另一个 RP ID 认证。服务端同时检查调用 origin,不能只比较主域名字符串。跨来源 iframe 或 Related Origin Requests 要额外评估用户是否清楚“正在为谁登录”,并在支持矩阵中单独测试。
不能把“页面显示了公司 Logo”当成来源证明。来源、RP ID、challenge 和签名必须由浏览器/认证器上下文与服务端共同验证。
第四步:按风险解释 UP、UV 与同步状态
UP 表示用户与认证器发生了交互;UV 表示认证器在本地完成了用户验证。普通登录可以按风险选择要求,转账、密钥导出或管理员操作则应要求 UV,并在服务端检查返回标志。
同步凭据提升跨设备可用性,但 NIST 指出同步会涉及密钥可导出性;它是否满足某个身份保证等级,要按部署策略判断。记录备份资格与状态,不能把“可同步”误称为“已经同步”或“设备绑定”。
第五步:设计恢复、迁移与撤销
用户丢失设备时,优先使用另一把已注册的 Passkey、企业恢复密钥或经过审查的强身份流程。恢复 token 必须短时、单次、绑定会话并可撤销;恢复后通知用户、轮换会话并让用户检查和删除旧凭据。
迁移密码时保留可控的过渡期,成功创建 Passkey 后逐步降低密码依赖,不在同一次请求中静默删除所有旧因素。每个 credential 都有独立撤销状态;异常计数器、风险设备和恢复事件进入审计流。
高质量示范回答
“我会先把安全目标分级。服务端每次注册和认证都生成一次性 challenge,放进短时会话;收到响应后验证 challenge、RP ID、origin、签名以及该操作要求的 UP/UV 标志,成功后立即消费 challenge。数据库只存公钥、credential ID、计数器、账号和备份状态,私钥不离开认证器。
跨来源 iframe 不默认开放,若必须使用就把调用 origin、顶层 origin 和 RP ID 写入测试矩阵。普通登录可接受符合策略的同步凭据,高风险操作要求 UV 或设备绑定。恢复优先使用其他强 Passkey 或企业恢复密钥,短时一次、风控和通知必须齐全;短信只能作为有明确风险承受度的补充,不能成为绕过强认证的永久后门。上线观察 challenge 重放、origin 不匹配、UV 不满足、恢复成功率和异常撤销事件。”
常见错误
- 只验证签名 → 签名正确不代表 challenge、RP ID 和 origin 正确 → 逐项校验并消费 challenge。
- 把 UP 当成 UV → 用户触碰认证器不等于本地完成身份验证 → 按高风险操作要求并检查 UV。
- 把同步 Passkey 说成设备绑定 → 同步状态与是否已同步是不同事实 → 记录备份资格/状态并按身份保证等级决策。
- 恢复直接发短信链接 → 最弱路径可接管整个账号 → 引入已有强因素、短时 token、风控和通知。
- 只按主域名校验来源 → origin 包含协议、主机和端口 → 比较规范化的完整 origin。
- challenge 可重复使用 → 拦截的 assertion 可能被重放 → 随机、短时、单次消费并绑定会话。
追问及应对
追问一:Passkey 为什么能抗钓鱼?
认证器根据来源和 RP ID 选择凭据,并对服务端 challenge 与上下文签名;钓鱼站点不能让认证器为另一个来源生成同一服务的有效证明。服务端仍必须验证 origin、RP ID 和 challenge。
追问二:为什么 challenge 不能只放在客户端?
服务端必须知道自己发出的随机值,才能判断响应对应当前登录意图并拒绝重放。客户端生成或单独保存的值不能证明服务端曾发起该次请求。
追问三:同步凭据是否一定不安全?
不应做二元结论。同步提升恢复性和跨设备体验,但密钥可导出性、提供商策略和组织身份保证要求不同。服务端应按风险等级检查备份标志,并对高风险操作要求更强因素。
追问四:用户把所有设备都丢了怎么办?
恢复流程必须被视为高风险认证:使用企业恢复密钥、另一种已审查的强因素或人工审核,限制时效与范围,通知用户并撤销未知凭据。不能因为“方便找回”而永久降低登录强度。