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

Webauthn公钥生成实践:公钥生成端及Axios传输问题咨询

WebAuthn 问题解答

1. publicKey 参数的生成位置

必须在服务端生成。WebAuthn的核心安全逻辑依赖服务端控制认证流程的关键参数,包括rp(依赖方信息)、user(用户信息)、challenge(随机挑战值)等。这些参数由服务端生成才能保证挑战的唯一性、不可预测性,避免客户端篡改参数引发的重放攻击或身份伪造风险。客户端仅负责将服务端生成的publicKey对象传递给navigator.credentials.create()或get()方法,不能自行生成核心参数。

2. 二进制/UTF格式数据的Axios传输方案

WebAuthn涉及的二进制数据(如公钥、challenge、认证响应中的attestationObject等)无法直接通过JSON传输,需通过URL安全的Base64编码转换为字符串后传输,具体流程如下:

服务端→客户端(传递publicKey参数)

  • 服务端将二进制数据(如challenge)转换为URL安全Base64字符串(替换+为-、/为_,移除末尾=填充),嵌入到publicKey对象中返回给客户端。
  • 客户端接收后,将字符串转回Uint8Array再调用WebAuthn API:
// 工具函数:URL安全Base64转Uint8Array
function base64UrlToUint8Array(base64Url) {
  const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
  const padded = base64.padEnd(base64.length + ((4 - base64.length % 4) % 4), '=');
  const rawStr = window.atob(padded);
  return Uint8Array.from([...rawStr].map(c => c.charCodeAt(0)));
}

// 从服务端获取注册/认证选项
const publicKeyOptions = await axios.get('/webauthn/options');
// 转换二进制字段
publicKeyOptions.challenge = base64UrlToUint8Array(publicKeyOptions.challenge);
// 调用WebAuthn注册API
const credential = await navigator.credentials.create({ publicKey: publicKeyOptions });

客户端→服务端(传递认证响应)

  • 客户端将Credential对象中的二进制数据转换为URL安全Base64字符串,封装到请求体中发送:
// 工具函数:Uint8Array转URL安全Base64
function uint8ArrayToBase64Url(uint8Array) {
  const base64 = window.btoa(String.fromCharCode(...uint8Array));
  return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}

// 处理注册响应并封装请求数据
const registrationPayload = {
  id: credential.id,
  rawId: uint8ArrayToBase64Url(credential.rawId),
  type: credential.type,
  response: {
    clientDataJSON: uint8ArrayToBase64Url(credential.response.clientDataJSON),
    attestationObject: uint8ArrayToBase64Url(credential.response.attestationObject)
  }
};

// 发送到服务端验证
await axios.post('/webauthn/verify', registrationPayload);

服务端侧处理

服务端收到URL安全Base64字符串后,解码回二进制数据即可进行验证。不同后端语言有现成工具支持,比如Node.js可直接用Buffer.from(base64UrlStr, 'base64url')完成转换,Java可使用Base64.getUrlDecoder(),Python可借助base64.urlsafe_b64decode()(注意补全=填充)。

内容的提问来源于stack exchange,提问作者chandra chaitanya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 09:20:13