You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用WebAuthn API创建凭证时如何处理用户取消操作?

WebAuthn 中区分用户取消与其他 NotAllowedError 的最佳实践

你的思路方向是对的,但需要补充额外的上下文判断,才能安全区分用户主动取消和系统级设备故障导致的NotAllowedError,避免误判影响用户体验。以下是具体的最佳实践方案:


核心区分逻辑

NotAllowedError确实会在两种场景抛出:

  1. 用户主动关闭验证弹窗、点击取消按钮
  2. 设备连接失败(如安全密钥未识别、蓝牙断开、生物识别设备不可用)

我们可以通过交互时间差和操作上下文来区分这两种场景:

1. 利用请求耗时辅助判断

  • 用户主动取消通常需要几秒的思考/操作时间,请求耗时一般会超过1-2秒
  • 设备连接失败往往是瞬间发生的,请求耗时通常在1秒以内

2. 结合前置状态检查

在调用navigator.credentials.create()前,可先做基础设备可用性检查(如检测是否支持WebAuthn、是否有已注册的设备),提前过滤部分设备故障场景,减少后续错误判断的复杂度。


优化后的代码实现

async function startCredentialCreation(options) {
  // 记录请求发起时间戳
  const requestStart = Date.now();
  // 切换加载状态
  toggleLoading(true);

  try {
    const credentials = await navigator.credentials.create(options);
    // 处理凭证创建成功的逻辑
    handleCredentialSuccess(credentials);
  } catch (err) {
    const elapsedTime = Date.now() - requestStart;
    toggleLoading(false);

    if (err instanceof DOMException && err.name === "NotAllowedError") {
      // 根据耗时区分场景
      if (elapsedTime > 1200) {
        // 用户主动取消:仅恢复按钮,可加温和提示
        showToast("已取消凭证创建,可再次尝试");
        return;
      } else {
        // 设备连接故障:给出明确错误提示
        showError("无法连接到你的安全设备,请检查设备是否正常连接后重试");
        return;
      }
    }

    // 处理其他类型错误
    showError("创建凭证时发生未知错误,请稍后重试");
    console.error("Credential creation failed:", err);
  }
}

// 辅助函数示例
function toggleLoading(isLoading) {
  // 切换加载动画和按钮显示状态
  document.getElementById("create-btn").style.display = isLoading ? "none" : "block";
  document.getElementById("loading-spinner").style.display = isLoading ? "block" : "none";
}

function showToast(message) {
  // 显示轻量提示
  const toast = document.createElement("div");
  toast.textContent = message;
  document.body.appendChild(toast);
  setTimeout(() => toast.remove(), 2000);
}

function showError(message) {
  // 显示错误提示
  document.getElementById("error-message").textContent = message;
}

额外注意事项

  • 不要依赖错误消息文本:不同浏览器的err.message内容不一致(如Chrome和Firefox的提示文字不同),仅可靠err.name判断错误类型
  • 测试多场景:在不同浏览器、不同设备(USB密钥、蓝牙密钥、Touch ID/Face ID)下测试,调整时间差阈值(比如部分设备响应慢,可把阈值调到1500ms)
  • 保持重试入口:无论哪种错误,都要确保用户能重新发起创建请求,不要让界面卡住

内容的提问来源于stack exchange,提问作者Gabriel Andrade

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 16:24:57