Double Submit Cookie的token怎么传到请求头里?

长孙一然 阅读 23

我按照文档做了Double Submit Cookie防护,但测试时发现后端收不到CSRF-TOKEN的请求头,只能拿到cookie里的值。这是为什么啊?

我的登录表单这样写的:



  
  


  document.cookie = `csrfToken=abc123; Path=/`;
  const form = document.querySelector('form');
  form.addEventListener('submit', () => {
    form.appendChild();
  });

后端检查时发现,请求头里没有X-CSRF-TOKEN字段,只能通过req.cookies获取到值。是不是应该把cookie的值自动加到请求头?我这样手动添加有问题吗?

我来解答 赞 9 收藏
二维码
手机扫码查看
2 条解答
Code°卫红
你的问题确实挺典型的,很多人在实现 Double Submit Cookie 时都会遇到类似的情况。我们一步步来看怎么解决。

首先你要明白一点,浏览器不会自动把 cookie 的值加到请求头里。document.cookie 只是设置了一个客户端的 cookie,但后端检查的是 HTTP 请求头里的字段,比如 X-CSRF-TOKEN,这两者是完全分开的。所以你需要手动把 cookie 的值取出来,再放进请求头。

### 具体步骤

1. **获取 cookie 值**
你可以写一个函数来解析 document.cookie,提取出 csrfToken 的值。

2. **将值附加到请求头**
对于表单提交来说,原生 HTML 表单是不会自动帮你添加自定义请求头的,所以你需要用 JavaScript 拦截表单提交,并通过 AJAX 或 Fetch API 来发送请求,同时手动设置请求头。

下面我给你写一个完整的解决方案:

---

### 代码示例

#### 1. 获取 CSRF Token 的函数
// 定义一个函数,用于从 document.cookie 中获取指定的 cookie 值
function getCookie(name) {
const value = ; ${document.cookie};
const parts = value.split(; ${name}=);
if (parts.length === 2) return parts.pop().split(';').shift();
}

// 测试一下是否能正确获取 csrfToken
console.log(getCookie('csrfToken')); // 应该输出 'abc123'


#### 2. 修改表单提交逻辑
document.addEventListener('DOMContentLoaded', () => {
const form = document.querySelector('form');

form.addEventListener('submit', (event) => {
event.preventDefault(); // 阻止默认的表单提交行为

// 获取 CSRF Token
const csrfToken = getCookie('csrfToken');
if (!csrfToken) {
console.error('CSRF Token not found in cookies!');
return;
}

// 使用 Fetch API 提交表单数据,并附加上 X-CSRF-TOKEN 请求头
fetch(form.action, {
method: form.method,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-CSRF-TOKEN': csrfToken, // 这里把 token 放到请求头中
},
body: new URLSearchParams(new FormData(form)), // 将表单数据序列化
})
.then(response => response.json())
.then(data => {
console.log('Success:', data);
})
.catch(error => {
console.error('Error:', error);
});
});
});


---

### 关键点解释

1. **为什么需要手动设置请求头?**
因为浏览器的安全策略,默认情况下不会把 cookie 的值放到自定义请求头里。你必须自己动手,把 cookie 的值取出来,再放到请求头里。

2. **为什么用 Fetch 而不是直接提交表单?**
原生 HTML 表单提交只能携带标准的 HTTP 头部,无法自定义头部字段(比如 X-CSRF-TOKEN)。而 Fetch 或 AJAX 则可以自由控制请求头。

3. **如何确保 CSRF Token 的安全性?**
- 只能在 HTTPS 环境下使用,避免中间人攻击。
- 不要直接暴露 token 在页面上,而是通过安全的接口动态生成并存储到 cookie 中。

---

### 注意事项

- 如果你的后端需要严格区分 X-CSRF-TOKENcsrfToken,确保前后端对字段名称一致。
- 测试时记得清空浏览器缓存或打开隐身模式,避免旧的 cookie 影响结果。
- 如果你用的是框架(比如 React、Vue),可以考虑在全局拦截器中统一处理 CSRF Token 的注入。

希望这些内容能帮到你!如果还有其他疑问,随时问我。
点赞 11
2026-02-01 21:19
书生シ海淇
你的问题出在表单提交时,没有正确把 csrfToken 的值加到请求头里。浏览器的表单默认是通过 application/x-www-form-urlencoded 提交的,这种方式是不会自动把 Cookie 的值转成请求头的。

先检查一下你的代码逻辑,问题主要在这儿:
1. 你在事件监听器里写了个 form.appendChild(),但你没传任何参数,这根本不会添加任何东西。
2. 表单提交是浏览器原生行为,默认不会带自定义请求头,你需要用 fetch 或者 AJAX 来手动控制请求头。

正确的做法是这样:

如果用 fetch
document.cookie = csrfToken=abc123; Path=/;

const form = document.querySelector('form');
form.addEventListener('submit', (e) => {
e.preventDefault(); // 阻止默认提交

const formData = new FormData(form);
fetch(form.action, {
method: 'POST',
body: formData,
headers: {
'X-CSRF-TOKEN': getCookie('csrfToken') // 从 Cookie 读取 token
}
});
});

function getCookie(name) {
const value = ; ${document.cookie};
const parts = value.split(; ${name}=);
if (parts.length === 2) return parts.pop().split(';').shift();
}


如果你非要保留表单的默认提交行为,那后端就必须从 Cookie 里读取 CSRF-Token,前端确实没法直接把 Cookie 值塞到请求头里。

另外吐槽一句,Double Submit Cookie 的确是个好办法,但有时候折腾起来挺让人头疼的,尤其是前后端配合不默契的时候。
点赞 14
2026-01-28 22:30