CSRF Token 必须显式传递且严格校验:表单用 hidden 字段,AJAX 从 DOM 读取;输出用户内容必用 htmlspecialchars();verifyToken 失败须立即终止并返回通用错误;禁用 session_id 作 token;登出时清空 token 缓存。

CSRF Token 必须在每个表单和 AJAX 请求中显式传递
ThinkPHP 自带的 token() 函数只生成 token,但不会自动注入到 AJAX 请求头或表单字段里——这是绝大多数权限接口被绕过的起点。你得自己确保每次提交都带上它,否则中间件校验直接失败。
常见错误现象:Token error 报错、POST 接口偶尔 403、登录后跳转丢失权限态。
- 表单中必须手动写:
- AJAX 请求需从页面 DOM 或 JS 变量里读取 token(别用
token()在 JS 里重生成):$.post('/admin/user/edit', { id: 1, name: 'a', __token__: $('#__token__').val() }) - 如果用 Vue/React 渲染表单,token 必须由后端渲染进初始 HTML 或通过独立接口返回,不能靠前端生成
输出用户可控内容前必须调用 htmlspecialchars() 或模板自动转义
ThinkPHP 模板默认开启 htmlentities 转义,但一旦你用了 {:} 或 这类非安全输出语法,XSS 就立刻生效。权限系统里最危险的是角色名、菜单名、操作日志中的用户名——这些常来自数据库直出,未经清洗。
使用场景:后台权限列表页展示角色描述、用户编辑页回显昵称、操作日志中显示请求参数值。
- 模板中一律用
{$role.desc|htmlspecialchars=ENT_QUOTES,UTF-8}显式过滤,不要依赖默认 - 控制器返回 JSON 给前端时,若字段含用户输入内容(如
$user['remark']),先过htmlspecialchars($user['remark'], ENT_QUOTES, 'UTF-8')再 encode - 禁用
think\template\driver\File::config(['autoescape' => false]),哪怕为了“兼容旧代码”也不行
verifyToken() 验证失败后必须终止执行,且不暴露具体失败原因
ThinkPHP 的 validateToken()(或中间件中调用的 Token::check())返回 false 时,很多人只加个提示就继续往下走,或者返回 token_invalid 这类明确错误码——这等于告诉攻击者“你猜对了 token 格式,只是值不对”,为爆破提供反馈。
性能影响:token 校验本身开销极小,但若放在权限判断之后才校验,会导致非法请求仍触发 DB 查询或 Redis 权限检查。
- CSRF 校验必须放在权限中间件之前,且失败时立即
abort(403)或return json(['code'=>403]) - 不要在响应体里返回
"msg": "token expired",统一用"msg": "Access denied" - 日志中可记录原始 token 值(用于审计),但绝不返回给客户端
Session 和 Token 生命周期要严格分离,禁止用 session_id 当 CSRF token
有人图省事把 session_id() 直接当 CSRF token 用,这是典型误区:session_id 是长期有效的会话标识,而 CSRF token 必须一次性或短时效。攻击者一旦拿到 session_id(比如通过 XSS 窃取),就能无限伪造请求。
兼容性影响:ThinkPHP 6.1+ 默认使用 think\middleware\Token 中间件,它基于 cache 驱动存 token,默认有效期 3600 秒;若你换成了 file 缓存,要注意并发写入冲突导致 token 失效。
- CSRF token 必须调用
token()生成,底层走的是Cache::tag('token')->set($key, $value, 3600) - 不要覆盖
Token::init()去改存储逻辑,除非你确认缓存驱动支持原子操作 - 用户登出时,记得调用
Cache::tag('token')->clear()清掉该用户所有未使用的 token
真正难的不是加几行 token 或转义函数,而是所有分支路径——包括异常处理、回调钩子、API 网关透传、甚至导出 Excel 的临时路由——都得被同一套规则覆盖。漏一个,前面全白做。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











