表单提交带了CSRF Token后后端还是报无效?

シ爱玲 阅读 76

我在登录表单里加了隐藏字段的CSRF Token,用JavaScript从API接口获取的,但每次提交后端还是返回“Token无效”。明明前端能正常拿到Token值,表单也正确显示在hidden input里,这是哪里出问题了?


<form id="loginForm" method="POST" action="/login">
  <input name="username" type="text">
  <input name="password" type="password">
  <input type="hidden" name="csrfToken" value="">
</form>

<script>
fetch('/api/csrf-token')
  .then(res => res.json())
  .then(data => {
    document.querySelector('[name="csrfToken"]').value = data.token;
  });
</script>

我检查了网络请求,发现表单提交时POST数据确实带有csrfToken参数,但后端PHP验证时$_POST[‘csrfToken’]总是空的。难道是表单提交方式有问题?或者服务端没正确设置Cookie同源?

我来解答 赞 10 收藏
二维码
手机扫码查看
1 条解答
司徒春芳
这个问题我也遇到过,坑了我半天。你代码看起来没问题,但实际上有个很隐蔽的陷阱:PHP 默认不会把 POST 数据里的 token 自动填充到 $_POST 里面,特别是你用的是自定义字段名。

你后端需要手动从 php://input 里解析 token。我猜你用的是类似 $_POST['csrfToken'] 直接取值的方式,但这种取法在某些情况下会取不到。下面是你需要改的后端代码:

// 先启用这个模式,让 PHP 能从 POST 中读取原始数据
parse_str(file_get_contents("php://input"), $postData);
$csrfToken = $postData['csrfToken'] ?? '';

// 然后再验证 $csrfToken 是否有效
if (!$csrfToken || !validateCsrfToken($csrfToken)) {
die('Token无效');
}


前端代码没问题,继续用你现在的逻辑就行。问题就在 PHP 默认处理 POST 数据的方式上,它对安全校验这种高级操作不太友好,得手动捞数据。

另外,检查一下 CSRF Token 的生成逻辑,确保你服务端有存下来(比如存在 session 里),不然验证逻辑也会失败。我之前就是忘了把 token 存 session,前端传对了后端还是报错,吐血。
点赞 7
2026-02-03 18:01