生物识别认证后如何安全传递用户身份?

小恩硕 阅读 57

我在用 Web Authentication API 做指纹登录,验证通过后怎么把用户身份传给后端才安全?直接发 user ID 会不会被伪造?

现在前端拿到 PublicKeyCredential 后,打算把 id 发给服务器,但不确定这样是否足够。试过只传 credential.id,但后端说还需要验证签名,可文档看得有点懵……

const cred = await navigator.credentials.get({
  publicKey: {
    challenge: Uint8Array.from("authChallenge", c => c.charCodeAt(0)),
    allowCredentials: [{ type: "public-key", id: storedCredentialId }]
  }
});
// 然后我直接发 cred.rawId 给后端?
fetch('/api/auth', { method: 'POST', body: JSON.stringify({ id: cred.id }) });
我来解答 赞 10 收藏
二维码
手机扫码查看
2 条解答
司空子阳
哈,WebAuthn这个确实容易让人懵。官方文档里说不能只传credential.id,这相当于只传了用户名没传密码。你需要把完整的认证响应发给后端验证。

正确做法是把这几个关键数据打包发给后端:
const authResponse = {
id: cred.id,
rawId: Array.from(new Uint8Array(cred.rawId)),
response: {
clientDataJSON: Array.from(new Uint8Array(cred.response.clientDataJSON)),
authenticatorData: Array.from(new Uint8Array(cred.response.authenticatorData)),
signature: Array.from(new Uint8Array(cred.response.signature)),
userHandle: cred.response.userHandle ? Array.from(new Uint8Array(cred.response.userHandle)) : null
}
};


后端要做三件事:
1. 验证clientDataJSON里的challenge是否和最初发出的一致
2. 用公钥验证签名是否有效
3. 检查authenticatorData里的标志位(比如用户验证标志)

我之前也踩过坑,以为传个id就行,结果被安全团队怼了。WebAuthn规范里明确要求必须验证签名链,不然和传统密码没区别。

另外记得用HTTPS,不然中间人攻击一抓一个准。MDN上有完整示例,你可以对照着看后端验证部分。
点赞 1
2026-03-06 11:16
玉萱的笔记
问题在于你只发了 credential id,没发签名数据,那后端拿什么验证?WebAuthn 的安全机制就是靠签名,你得把 response 里的签名和原始数据一起发过去。

正确做法是把 clientDataJSON、authenticatorData、signature 都发给后端:

const cred = await navigator.credentials.get({
publicKey: {
challenge: Uint8Array.from("authChallenge", c => c.charCodeAt(0)),
allowCredentials: [{ type: "public-key", id: storedCredentialId }]
}
});

// 发完整的签名数据给后端
const payload = {
id: cred.id,
rawId: arrayBufferToBase64(cred.rawId),
clientDataJSON: arrayBufferToBase64(cred.response.clientDataJSON),
authenticatorData: arrayBufferToBase64(cred.response.authenticatorData),
signature: arrayBufferToBase64(cred.response.signature),
userHandle: cred.response.userHandle ? arrayBufferToBase64(cred.response.userHandle) : null
};

fetch('/api/auth', {
method: 'POST',
body: JSON.stringify(payload)
});

function arrayBufferToBase64(buffer) {
return btoa(String.fromCharCode(...new Uint8Array(buffer)));
}


后端用注册时存的公钥验证 signature,验证通过了才能确认是你本人,不是别人伪造的 user id。
点赞 4
2026-03-01 08:00