帮助用户更顺畅地采用通行密钥

发布时间:2025 年 5 月 9 日

通行密钥提供强大的防钓鱼式攻击的身份验证机制。不过,让用户采用这些功能可能会带来阻力。借助自动创建通行密钥功能,您可以在适当的时机为用户创建通行密钥,前提是用户已为您的网站保存密码。条件创建是 WebAuthn 规范的一部分,可实现自动创建通行密钥。

运作方式

为了帮助用户更方便地采用通行密钥,请使用名为条件创建的 WebAuthn API 功能。借助条件创建功能,您的网站可以为用户请求通行密钥,而无需用户执行任何操作。

当满足以下条件时,此流程会正常运行:

  • 用户在默认密码管理工具中保存了密码。
  • 该密码最近曾被使用过。理想情况下,在基于密码的登录成功后立即调用条件创建。

如果这两个条件都满足,您可以调用条件创建来请求密码管理器为用户创建通行密钥。成功创建通行密钥后,系统会根据密码管理器的不同通知用户。

具有条件创建的通行密钥请求流程。

兼容性

macOS 上的 Safari 和 iOS 上的所有浏览器以及桌面版 ChromeAndroid 版 Chrome 均支持有条件创建。

实现有条件创建

自动创建通行密钥基于一项名为条件创建的 WebAuthn API 功能。这些是常规 WebAuthn create() 请求,其中 mediation 参数设置为 "conditional",这与 get() 请求的通行密钥自动填充类似。

在用户使用密码登录后,使用条件式创建。创建是否成功取决于密码管理器以及是否满足某些条件。这些条件可能因密码管理工具而异,并且可能会随时间推移而发生变化。例如,在搭载 Google 密码管理工具 (GPM) 的 Chrome 中,用户必须最近使用保存的网站密码登录过。

如果浏览器成功创建通行密钥,则会返回公钥凭据。将此凭据发送到您的后端,以完成注册并启用未来的身份验证。

功能检测

您可以通过调用 PublicKeyCredential.getClientCapabilities() 来确定浏览器是否支持有条件创建。查看返回的对象是否包含 conditionalCreate 属性的 true

if (window.PublicKeyCredential && PublicKeyCredential.getClientCapabilities) {
  const capabilities = await PublicKeyCredential.getClientCapabilities();
  if (capabilities.conditionalCreate) {
    // Conditional create is available
  }
}

如果 getClientCapabilities 不可用,则条件性创建也不可用。

有条件地创建通行密钥

如需执行自动创建通行密钥操作,请调用 navigator.credentials.create(),但使用 mediation: "conditional",如下所示。

const cred = await navigator.credentials.create({
  publicKey: options,
  // Request conditional creation
  mediation: 'conditional'
});

您应在用户登录后立即使用自动通行密钥创建功能,这样才能最大限度地满足密码管理器的自动创建条件。

您可以将生成的公钥凭据发送到服务器,以验证并注册通行密钥。在服务器上,确保用户已登录。

注意事项

条件创建本身并不难实现,但在将此功能实际集成到现有系统中时,需要注意以下几点。

在服务器上忽略用户存在性和用户验证

注册响应将“用户存在”和“用户已验证”都返回为 false,因此服务器应在凭据验证期间忽略这些标志

在执行自动通行密钥创建之前中止正在进行的 WebAuthn 调用

当 RP 希望用户使用通行密钥或密码登录时,执行条件性获取是最佳选择。这可能会导致条件性 get 调用在执行条件性创建之前被取消。

为此,您需要使用 AbortController 并调用 .abort()

// To abort a WebAuthn call, instantiate an AbortController.
const controller = new AbortController();

const cred = await navigator.credentials.get({
  publicKey: options,
  signal: controller.signal,
  // Request conditional get
  mediation: 'conditional'
});

// Abort the call
controller.abort();

优雅地忽略异常

执行有条件的通行密钥创建时,在以下几种情况下,您应忽略异常:

  • InvalidStateError:通行密钥提供程序中已存在通行密钥(别忘了指定 excludeCredentials)。
  • NotAllowedError:创建通行密钥不符合条件。
  • AbortError:WebAuthn 调用已中止。

在这些情况下显示错误可能会让用户感到困惑,因为浏览器会以静默方式处理这些错误:仅在成功时显示通知,而失败不会触发可见的消息。

在注册通行密钥失败时发出信号

如果通行密钥已创建但未能成功在服务器上注册,用户将无法成功登录。如果通行密钥提供方和服务器之间的通行密钥列表不一致,可能会发生这种情况。

为避免这种情况,请使用 Signal API 来保持它们的一致性

不支持从无密码登录升级

此时,有条件地创建通行密钥需要用户输入有效密码。这意味着,无密码登录方法(例如魔法链接、电话号码验证或身份联合)不符合此条件。

摘要

自动创建通行密钥有助于加快通行密钥在您网站上的普及,帮助您的网站用户从密码过渡到更安全的身份验证方法。

如需详细了解通行密钥,请先参阅使用通行密钥进行无密码登录