防御会话固定最核心动作是登录成功后立即调用session_regenerate_id(true),且必须在写入关键$_session数据之后、任何输出之前执行;php需启用session.use_strict_mode=1,并配合use_only_cookies、httponly等配置。

登录成功后必须立即调用 session_regenerate_id(true)
这是防御会话固定最核心、不可绕过的动作。ThinkPHP、原生PHP甚至大多数自研框架都不自动执行它——框架只管启动会话,不负责轮换ID。攻击者一旦提前让用户携带了 PHPSESSID=abc123(比如通过钓鱼链接或恶意JS注入),而你登录后没重置,那个 abc123 就直接绑定了用户身份,攻击者立刻可接管。
实操要点:
-
session_regenerate_id(true)必须在写入关键$_SESSION数据(如$_SESSION['user_id'])之后、任何输出(echo、header()、json()、redirect())之前执行,否则会因 headers 已发送报错Cannot modify header information -
true参数表示删除旧会话文件,避免残留数据被读取;仅传false或不传参数,旧 session 文件仍存在,风险未解除 - 不要用
session_destroy() + session_start()替代——它不保证新 ID 与旧 ID 无统计关联,且容易漏掉清理旧文件
PHP配置必须启用 session.use_strict_mode = 1
这个配置不是“锦上添花”,而是堵住会话固定最基础的入口。设为 1 后,PHP 拒绝所有未存在于服务端存储中的会话 ID 初始化请求——也就是说,攻击者伪造的、从未被 session_start() 创建过的 PHPSESSID,服务器直接无视,连会话都不会建立。
但注意:它防不住“合法但受控”的ID。比如攻击者先访问一次你的首页,拿到一个真实生成的 PHPSESSID=xyz789,再诱导用户带着它打开登录页——这个 ID 是服务端已知的,use_strict_mode 不拦截。所以它必须和 session_regenerate_id(true) 配合使用。
其他配套配置建议一并设置:
-
session.use_only_cookies = 1:强制只从 Cookie 读取 ID,禁用 URL 参数(?PHPSESSID=...)和 POST 传输 -
session.cookie_httponly = 1:阻止 XSS 脚本通过document.cookie窃取 -
session.cookie_secure = 1:仅在 HTTPS 下发送 Cookie,防止明文泄露 -
session.use_trans_sid = 0:彻底关闭透明 SID 传递,避免日志或 Referer 泄露
ThinkPHP项目里不能依赖框架默认行为
ThinkPHP 的 session_start() 完全交由 PHP 底层控制,它不会在 Auth::attempt() 或登录逻辑结束时自动调用 session_regenerate_id()。很多开发者误以为“用了框架就安全了”,结果上线后仍被扫描出会话固定漏洞。
正确做法是在登录控制器方法末尾手动插入:
session_regenerate_id(true); $_SESSION['user_id'] = $user->id; // 此后才能跳转或返回 JSON
常见踩坑点:
- 在中间件或前置钩子里调用——太早,用户还没认证,重置后反而丢失登录态
- 放在
return redirect(...)之后——语句根本不会执行 - 用
Cookie::set('PHPSESSID', ...)手动覆盖——无效,PHP session 机制不认这个
别只盯着登录点,敏感操作前也该重置
登录是最高危节点,但不是唯一节点。用户修改密码、切换角色、升级权限、绑定手机号等操作,本质上都是“身份状态重大变更”,此时若继续沿用旧会话 ID,攻击者只要此前拿到了它,就能在这些高权限动作发生时同步受益。
建议策略:
- 对所有涉及权限跃迁的操作,在验证通过后、写入新状态前,再次调用
session_regenerate_id(true) - 配合短会话生命周期(如
session.gc_maxlifetime = 900,即15分钟),降低 ID 复用窗口 - 避免在 JS 前端拼接含
PHPSESSID的 URL,Vue/React 项目尤其注意 axios 请求头是否意外透传了旧 Cookie
session_regenerate_id(true),而是确保它出现在所有该出现的位置、且永远在输出之前执行。配置可以一次设好,代码逻辑却容易随业务迭代被绕过或遗忘。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











