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

Django+Djoser集成WebAuthn时签名验证失败问题

解决WebAuthn注册签名验证失败问题

核心问题定位

你遇到的Authentication rejected. Error: Invalid signature received.错误,主要是因为后端验证时缺少关键的user_id参数,导致签名验证不匹配。以下是具体修复步骤:


1. 补充WebAuthnRegistrationResponse的user_id参数

在SignUpView的post方法中,创建WebAuthnRegistrationResponse时必须传入user_id=co.ukey——因为前端注册时使用的user_id就是这个值,后端验证时需要对应上才能通过签名校验:

webauthn_registration_response = WebAuthnRegistrationResponse(
    rp_id=settings.DJOSER["WEBAUTHN"]["RP_ID"],
    origin=settings.DJOSER["WEBAUTHN"]["ORIGIN"],
    registration_response=request.data,
    challenge=co.challenge,
    user_id=co.ukey,  # 新增此行,与注册请求时的user_id一致
    none_attestation_permitted=True,
)

2. 从CredentialOptions安全获取用户名

避免直接从request.data取用户名,改用已验证过的co.username,防止前端篡改:

# 替换原代码中的user获取逻辑
user = User.objects.get(username=co.username)

3. 修正凭证数据的存储格式(潜在问题)

直接对credential_id和public_key调用decode()会导致字节数据存储错误,改用base64 URL安全编码存储,和Djoser原实现保持一致:

import base64

# 替换原存储逻辑
co.credential_id = base64.urlsafe_b64encode(webauthn_credential.credential_id).decode("utf-8")
co.public_key = base64.urlsafe_b64encode(webauthn_credential.public_key).decode("utf-8")

4. 验证前端传递的响应完整性

确保前端使用@simplewebauthn/browser返回的完整registrationResponse直接传递给后端,不要修改signature、userHandle等核心字段。示例前端代码:

import { startRegistration } from "@simplewebauthn/browser";

// 获取注册选项
const registrationOptions = await fetch("/webauthn/signup/request", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ username: "你的用户名", display_name: "你的昵称" }),
}).then(res => res.json());

// 发起WebAuthn注册
const registrationResponse = await startRegistration(registrationOptions);

// 提交注册结果
await fetch(`/webauthn/signup/${registrationOptions.user.id}`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(registrationResponse),
});

5. 确认RP ID和Origin配置正确

检查settings.DJOSER["WEBAUTHN"]中的配置:

  • RP_ID必须是不带协议、端口的域名,例如"example.com"(开发环境用"localhost")
  • ORIGIN必须是前端完整的源,例如"https://example.com"或"http://localhost:4200"

两者不匹配会直接导致签名验证失败。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 05:55:34