ThinkPHP6接口Token验证失败的核心原因是服务端比对时找不到匹配值,需检查前端是否正确传递__token__字段、Session是否正常、中间件配置是否干扰、Token是否新鲜有效。

ThinkPHP6 接口 Token 验证失败,核心问题不是“没传 Token”,而是服务端比对时找不到匹配值——要么前端根本没送、送错了位置,要么服务端校验逻辑被干扰或配置不匹配。下面从高频场景出发,直击关键点。
检查表单或请求是否正确携带 __token__ 字段
默认字段名是 __token__(两个下划线),不是 _token、csrf_token 或其他变体。提交前务必确认:
- 模板中已调用
{:token()}或{{ csrf_token() }},且生成的 HTML 确实包含<input type="hidden" name="__token__" value="abc123..."> - 浏览器 Network → Payload 中存在
__token__字段,且值与页面源码中的一致 - Ajax 提交时不能依赖自动注入:fetch/axios 不会自动带隐藏域,需手动读取并塞进 data,例如
form.dataset.token或document.querySelector('[name="__token__"]').value(注意唯一性) - 若用 JSON 提交(
Content-Type: application/json),必须把"__token__": "xxx"写进请求 body 对象里,不能放 headers
确认 Session 正常工作且未被覆盖
Token 值存在 Session 中,比对失败往往源于 Session 异常:
- 入口文件或配置中已开启 Session(
'session' => true),且服务器临时目录可写 - 跨子域名或 HTTPS 访问时,检查
session.cookie_domain和session.cookie_secure是否匹配当前请求协议与域名 - 避免多标签页同时打开同一表单页——TP6 默认 Token 一次性有效,旧页刷新后新 Token 生效,但旧页仍可能提交过期值
排查中间件和全局配置干扰
TP6 开启 'token_on' => true 后,所有 POST 接口都会强制校验,包括 API 路由:
立即学习“PHP免费学习笔记(深入)”;
- 不需要 Token 校验的接口,应在路由定义中排除:
->middleware('token')->except(['api/save']) - 调试模式(
APP_DEBUG = true)会导致输出缓冲区残留内容,微信/小程序等第三方平台验证时会因响应体含多余字符(如 Trace 信息)而失败,务必设为false - 确保验证逻辑前执行
ob_clean()清空输出缓冲,尤其在微信 token 验证接口中
验证 Token 是否真正生成并生效
别只看有没有字段,要看值是否新鲜、是否同步:
- 刷新页面后,源码中的
__token__value 必须变化;不变说明模板未重新渲染或缓存了静态 HTML - V6.1+ 使用
csrf_token()时,需先调用think\facade\Form::token()初始化,否则返回空字符串 - 禁用浏览器缓存或使用无痕模式测试,排除 CDN、Nginx 缓存返回陈旧 Token 的可能



















