密码作为互联网最古老的认证方式,缺陷已经暴露得越来越明显:用户倾向于设置弱密码、在多个网站复用同一密码,而服务端一旦数据库被拖,哈希再强也挡不住撞库攻击。Passkeys通行密钥是基于FIDO2和WebAuthn标准构建的新一代认证方案,它用非对称加密彻底替代了共享秘密,让钓鱼攻击在理论上失效。这篇文章带你从原理到实践,完整理解通行密钥的工作机制与落地方式。

Passkeys的核心原理:为什么它天然抗钓鱼
传统密码的本质是一个共享秘密,客户端和服务器都知道同一个字符串,任何一方泄露都会导致账号失守。通行密钥则完全不同,它基于公私钥密码体系。用户的设备在注册阶段生成一对密钥,私钥永远保存在本地设备的安全芯片或系统密钥链中,永远不会离开设备,只有公钥被上传到服务器。
认证时,服务器发送一个随机挑战值,设备用私钥对挑战值签名后返回,服务器再用之前保存的公钥验签。整个过程服务器不持有任何秘密,即便数据库被完全攻破,攻击者拿到的也只是一堆无法用来登录的公钥。这也是为什么FIDO联盟宣称Passkeys能够从根本上消除撞库和拖库风险。
抗钓鱼的实现则更加巧妙。私钥在生成时会与网站的源(Origin)绑定,签名时浏览器和操作系统会强制校验当前页面所属的域名。攻击者做了一个一模一样的假冒登录页,浏览器在webauthn调用时发现域名不匹配,会直接拒绝签名操作。用户即使被骗到了钓鱼网站,也泄漏不了任何凭据。这一点是密码和短信验证码永远做不到的,短信验证码甚至会因为用户误填到钓鱼页而直接被盗。
Web开发中如何接入Passkeys登录
在浏览器端,通行密钥通过navigator.credentials下的两个API完成交互:create负责注册新凭据,get负责后续认证。下面演示注册阶段的基本写法,注意这些API要求页面必须运行在HTTPS环境或localhost下。
// 注册通行密钥
const credential = await navigator.credentials.create({
publicKey: {
// challenge 必须由服务端生成并随机,防止重放攻击
challenge: base64ToArrayBuffer(serverChallenge),
rp: {
name: '我的应用',
id: 'example.ipipp.com' // 绑定域名,子域名可共用凭据
},
user: {
id: new TextEncoder().encode('user-10086'),
name: 'zhangsan@example.ipipp.com',
displayName: '张三'
},
pubKeyCredParams: [
{ type: 'public-key', alg: -7 }, // ES256
{ type: 'public-key', alg: -257 } // RS256
],
authenticatorSelection: {
residentKey: 'required', // 创建可发现凭据,支持无用户名登录
userVerification: 'preferred' // 优先要求生物识别或系统锁屏验证
},
timeout: 60000,
attestation: 'none'
}
});
// 将 credential 中的 id、rawId、公钥发回服务端保存
认证阶段流程类似,调用navigator.credentials.get并传入服务端下发的挑战值和允许的凭据ID列表。服务端收到签名结果后,需要用保存的公钥对签名进行验证,同时检查挑战值、签名计数器是否匹配。签名计数器用于检测克隆的认证器,如果计数值没有递增反而回退,服务端应当提高警惕甚至吊销凭据。
服务端验签可以直接使用成熟的库,Node.js生态中SimpleWebAuthn是比较流行的选择,Java可以用java-webauthn-server,Go有go-webauthn。自己手写验签逻辑容易在格式校验上踩坑,比如COSE密钥格式的解析、clientDataJSON中的crossOrigin字段检查等,建议优先借助库来保证安全性。
与密码加双因素认证的对比及现实落地考量
从安全模型上看,通行密钥相当于把知识因素和持有因素合二为一:用户需要解锁设备(生物识别或PIN,属于本地区域内验证),设备本身持有私钥。相比密码加短信双因素,它既不怕钓鱼,也不怕SIM卡被劫持。从体验上看,一次指纹或面容识别即可完成登录,比输入密码再等短信快得多。
不过落地时也有几个现实问题需要权衡。首先是恢复路径:如果用户所有设备都丢失了,没有绑定恢复邮箱或备用凭据的账号将无法找回,所以绝大多数系统仍然需要保留至少一种备用登录方式,比如一次性恢复码。其次是平台生态依赖,目前Apple、Google和Microsoft都支持通行密钥在各自生态内云同步,但跨平台迁移仍在逐步完善,企业内网场景可能更倾向配合硬件安全密钥使用。最后是老设备兼容问题,iOS 16之前的设备和部分安卓旧版本不支持Passkeys,灰度阶段建议采用密码与通行密钥并存的渐进策略。
另一个容易被忽视的细节是账号合并与多设备管理。用户可能在手机和电脑上分别创建了多个通行密钥,服务端应该允许一个账号绑定多个凭据,并提供凭据列表管理界面,显示每个凭据的创建时间和最近使用时间,方便用户主动清理丢失设备上的凭据。这些产品层面的细节往往比技术接入本身更影响整体方案的成败。
总体来看,Passkeys代表了认证技术的一次范式转移,从保护一个共享秘密变成了彻底消灭共享秘密。对于新项目,接入成本已经很低,主流浏览器和移动端支持也基本齐备,完全可以把通行密钥作为首选登录方式,密码降级为兼容选项。随着三大平台的持续推动,密码退出历史舞台只是时间问题,越早适应这套体系,越能在安全性和用户体验上占得先机。