ThinkPHP默认不启用Cookie安全标志,secure和httponly均为false;必须在config/app.php的'cookie'=>[]中显式配置'secure'=>true、'httponly'=>true,并在反向代理下补充'https'=>true或强制$_SERVER['HTTPS']='on'。

ThinkPHP 默认不启用 Cookie 安全标志,secure 和 httponly 都是 false,这意味着只要没手动配置,PHPSESSID 或自定义 Cookie 就可能被明文传输、被 XSS 脚本读取——劫持风险直接拉满。
config/app.php 里必须显式设 secure 和 httponly
ThinkPHP 6 的 Cookie 配置只认 config/app.php 中的 'cookie' => [] 块,改 config/cookie.php 或 config/cache.php 完全无效。
关键配置项必须写全:
-
'secure' => true:强制 Cookie 只走 HTTPS,但注意——若部署在反向代理后(如 Nginx 终止 HTTPS),框架可能检测不到 HTTPS,此时要额外在config/app.php里加'https' => true,或在public/index.php开头硬写$_SERVER['HTTPS'] = 'on'; -
'httponly' => true:阻止document.cookie读取,对 Session ID 类 Cookie 是刚需 -
'samesite' => 'Lax':防 CSRF,比None更安全;若必须用None,则secure必须为true,否则浏览器拒绝接收 -
'domain' => '.yourdomain.com':注意开头的点号,否则子域间 Cookie 不共享
登录后必须调用 session_regenerate_id(true)
ThinkPHP 不自动做会话固定防护。用户登录成功时,如果沿用登录前的 Session ID,攻击者只需诱导用户访问带固定 ID 的链接(比如分享的含 PHPSESSID=xxx 的 URL),就能复用该会话。
立即学习“PHP免费学习笔记(深入)”;
正确做法是在认证通过、写入用户数据前立刻刷新:
- 调用
session_regenerate_id(true),true表示删除旧 session 文件;漏掉这个参数,旧文件残留,仍可被重放 - 别用
Session::clear()或Session::destroy()替代——它们只清数据,不换 ID - 确保这行代码在
session_start()之后、且在写入$_SESSION['uid']等敏感字段之前执行
禁用 trans_sid 防 URL 泄露 Session ID
PHP 默认可能开启 session.use_trans_sid,一旦启用,所有相对 URL 都会被自动拼上 ?PHPSESSID=xxx,极易被代理、Referer、访问日志泄露。
必须在 session_start() 之前关闭:
ini_set('session.use_trans_sid', '0');-
ini_set('session.use_only_cookies', '1');:强制只走 Cookie,禁用 URL fallback - ThinkPHP 的
Session::init()内部虽调用session_start(),但不接管 ini 设置,所以你得在应用初始化早期(如app/middleware.php或app/common.php开头)就执行这两句
别信 Request::isSsl() 动态判断 secure
有人想“智能”地根据当前请求是否 HTTPS 来动态设 secure,比如在配置里写 'secure' => Request::isSsl() ——这不行。
原因很实际:
-
Request::isSsl()依赖$_SERVER变量,而反向代理场景下它常返回false,哪怕实际是 HTTPS - Cookie 配置在框架启动早期就加载,此时 Request 对象可能还没初始化,调用会报错或返回默认值
- 最稳妥的方式就是硬编码
'secure' => true,并配合'https' => true或服务器环境变量兜底
真正容易被忽略的是:开发环境没 HTTPS 时设了 secure => true,会导致 Cookie 根本不发送,登录反复失败——测试阶段务必确认环境协议与配置匹配。



















