必须启用并校验CSRF Token:PHP 8.0起无自动防护,需手动用bin2hex(random_bytes(32))生成安全令牌,存入$_SESSION并嵌入表单,提交时用hash_equals()比对,验证后建议刷新令牌,同时结合SameSite Cookie与AJAX头传输等多层防护。

必须启用并校验 CSRF Token
PHP 8.0 不再提供自动防护机制,CSRF 防御完全依赖手动实现。核心是为每个敏感操作生成一次性、不可预测的令牌,并在服务端严格比对。
- 使用 session_start() 启动会话(必须在任何输出前调用)
- 生成安全 Token:推荐 bin2hex(random_bytes(32)),避免
md5(time().rand())等弱随机方式 - 将 Token 存入 $_SESSION['csrf_token'],不要存 Cookie 或 URL 中
- 表单中嵌入:
<input type="hidden" name="token" value="= htmlspecialchars($_SESSION['csrf_token']) ?>"> - 提交时用 hash_equals() 安全比对,防止时序攻击:
if (!hash_equals($_SESSION['token'], $_POST['token'])) { die('Invalid'); } - 验证通过后建议刷新 Token(重新生成并覆盖 Session 值),防止重放
绑定上下文增强 Token 安全性
单一 Token 全局复用风险高,应按业务场景细化控制范围。
- 敏感操作(如修改密码、删除账号)使用独立 Token,不与普通表单共用
- 可将 Token 与用户 ID 或 IP 片段哈希绑定,例如:
sha1($user_id . substr($_SERVER['REMOTE_ADDR'], 0, 7)) - Session 过期或用户登出时,主动 unset($_SESSION['csrf_token'])
- 禁止 GET 请求执行状态变更(如
/delete?id=123),所有敏感动作强制走 POST + Token
配合 SameSite Cookie 属性限制跨站携带
SameSite 是浏览器级防护层,不能替代 Token,但能显著降低攻击面。
- PHP 7.3+ 可直接设置:
session_set_cookie_params(['samesite' => 'Lax']); - 生产环境推荐 Lax(兼顾兼容性与安全性),登录/支付等关键流程可设为 Strict
- 确保 session.cookie_httponly = On 和 session.cookie_secure = On(HTTPS 环境下)
- 注意:SameSite 对旧版浏览器无效,Token 校验仍是唯一可信防线
AJAX 请求也要带 Token 并校验
前后端分离场景下,CSRF 风险同样存在,不能只保护传统表单。
立即学习“PHP免费学习笔记(深入)”;
- 前端在请求头中添加:
headers: { 'X-CSRF-Token': '= $_SESSION['csrf_token'] ?>' } - 后端从 $_SERVER['HTTP_X_CSRF_TOKEN'] 读取并比对
- 若使用 Fetch 或 Axios,需显式配置
credentials: 'same-origin' - 避免把 Token 写死在 JS 文件或全局变量中,防止被 XSS 泄露



















