PHP CSRF漏洞最核心的解决方式是引入一次性、绑定会话的随机令牌(CSRF Token),并配合安全的验证逻辑;需用random_bytes()生成、绑定Session、表单隐藏域嵌入、hash_equals()恒定时间校验、验证后立即失效,并辅以SameSite=Lax Cookie策略。

PHP CSRF 漏洞最核心的解决方式是引入一次性、绑定会话的随机令牌(CSRF Token),并配合安全的验证逻辑。它不是可选功能,而是所有涉及状态变更的操作(如登录、转账、修改密码、删除内容)必须具备的基础防护。
生成强随机 Token 并绑定 Session
Token 必须不可预测、不复用、不泄露。PHP 8.4 及以上推荐使用 random_bytes() 生成,避免 rand() 或时间戳拼接:
- 启动 Session 后检查是否已存在 Token,若无则生成:
$_SESSION['csrf_token'] = bin2hex(random_bytes(32)); - Token 必须与当前用户 Session 绑定(不能全局共享),确保攻击者无法通过自己账号预取后复用
- 不建议将 Token 存入 Cookie 或 GET 参数——易被日志、Referer、代理缓存泄露
在表单中正确嵌入并提交 Token
所有敏感操作的表单(仅限 POST/PUT/DELETE)都需包含隐藏字段:
- 输出前必须用
htmlspecialchars()转义,防止 XSS 篡改或窃取 Token:<input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($_SESSION['csrf_token'], ENT_QUOTES, 'UTF-8'); ?>"> - 禁止在 URL 中传递 Token(如
?csrf_token=xxx),GET 请求本身不应触发状态变更 - AJAX 请求也需携带该 Token,通常放在请求头(如
X-CSRF-Token)或请求体中
服务端严格校验并即时失效
验证环节极易出错,关键点在于“防绕过”和“防重放”:
立即学习“PHP免费学习笔记(深入)”;
- 必须先确认 Session 已激活:
if (session_status() !== PHP_SESSION_ACTIVE) die('Invalid session'); - 使用
hash_equals()进行恒定时间比对,杜绝时序攻击:if (!hash_equals($_SESSION['csrf_token'] ?? '', $_POST['csrf_token'] ?? '')) { ... } - 验证通过后立即销毁旧 Token:
unset($_SESSION['csrf_token']);,或生成新 Token 替换(实现单次有效) - 拒绝处理缺失 Token、空值、类型不符(如数字或布尔)的请求,不回退到宽松逻辑
叠加 SameSite Cookie 属性作为辅助防线
虽不能单独依赖,但设置 Cookie 的 SameSite=Lax(推荐)或 Strict 可显著降低部分 CSRF 场景风险:
- 在
session_start()前或setcookie()时显式声明:session_set_cookie_params(['samesite' => 'Lax']); - 搭配
Secure和HttpOnly标志,防止 Cookie 被 JS 读取或明文传输 - 注意:SameSite 对 JSON API、iframe 嵌入等场景支持有限,仍需 Token 主控



















