关于TP8.0中,SESSION未自动保存的原因分析

2025年3月15日 999+浏览

1、简述

因之前用的tp5,漏洞太多,然后我尝试用tp8,然而,不管我怎么设置,我发现服务器端的session文件目录始终是空的,这意味着,session并没有自动保存,但是调试过程中也没有报错。最后查阅官方文档以及大量资料才发现,要在app/middleware.php 里面配置开启session,而不是config/middleware.php,于是,问题已成功解决!至于原因,我认为有可能是BUG。下面我就把解决过程中所有重要操作都写一下,送给有缘人。

问题成功解决的截图01

2、区别一下config与app目录下的两个middleware.php

①、作用范围‌

文件作用范围适用场景
config/middleware.php全局中间件‌(对所有应用生效)跨应用共享的中间件(如日志、跨域处理)
app/middleware.php应用中间件‌(仅对当前应用生效)特定应用的中间件(如权限校验、Session)

②、执行顺序‌

  • 全局中间件 (config/middleware.php):‌在应用中间件之前执行,优先级更高。
// config/middleware.php(全局)
return [
    \app\middleware\GlobalMiddleware::class,  // 先执行
];
  • 应用中间件 (app/middleware.php):‌在全局中间件之后执行,优先级较低。

// app/middleware.php(应用级)
return [
\think\middleware\SessionInit::class, // 后执行
];

③、典型配置差异

  •  ‌全局中间件示例 (config/middleware.php)
// 全局中间件,影响所有应用
return [
// 跨域处理中间件(所有应用生效)
\think\middleware\AllowCrossDomain::class,
// 全局请求日志中间件
\app\middleware\LogRequest::class,
];
  •  ‌应用中间件示例 (app/middleware.php)
// 应用中间件,仅当前应用生效
return [
// Session初始化(仅当前应用需要Session时加载)
\think\middleware\SessionInit::class,
// 用户权限校验(如Admin应用独有)
\app\admin\middleware\AuthCheck::class,
];

④、‌多应用模式下的差异‌

模式config/middleware.phpapp/middleware.php
单应用模式等同于全局中间件,所有请求强制加载应用级中间件,但优先级低于全局中间件
多应用模式对所有子应用生效(如 app/adminapp/api仅对当前子应用生效(如 app/api 的中间件)

3、调试技巧

如果无法判断是哪个文件生效或者要想知道文件的执行顺序,那么:

查看中间件加载顺序‌:在入口文件或控制器中输出中间件堆栈:

use think\facade\Middleware;
dump(Middleware::getMiddlewareStack());

验证执行顺序‌:在中间件的 handle 方法中添加日志:

public function handle($request, \Closure $next) {
    Log::write('GlobalMiddleware executed');
    return $next($request);
}

4、其它解决过程

  • 官方文档指出Session功能默认是没有开启的,如果你需要使用Seesion,需要在全局的中间件定义文件中加上下面的中间件定义:
    'think\middleware\SessionInit'
<?php

//单应用:app/middleware.php,   全局:config/middleware.php
// 全局中间件定义文件
return [
    // 全局请求缓存
    // \think\middleware\CheckRequestCache::class,
    // 多语言加载
    // \think\middleware\LoadLangPack::class,
    // Session初始化
     \think\middleware\SessionInit::class
];
  • 配置config/session.php
<?php
// +----------------------------------------------------------------------
// | 会话设置
// +----------------------------------------------------------------------

return [
    // session name
    'name'           => 'PHPSESSID',
    // SESSION_ID的提交变量,解决flash上传跨域
    'var_session_id' => '',
    // 驱动方式 支持file cache
    'type'           => 'file',
    // 存储连接标识 当type使用cache的时候有效
    'store'          => null,
    // 过期时间
    'expire'         => 1440,
    // 前缀
    'prefix'         => '',
    // 是否自动开启 session
    'auto_start' => true,
    // session 保存路径

    'save_path'       => '/temp/thinkphp8/runtime/session',
];
  • 服务器端:
php.ini 中的   session.save_path 要开启,并且与thinkphp 的session配置要一致。
session.save_path = "/temp/thinkphp8/runtime/session"

  • 配置session目录的权限
//配置属组,应于apache或nginx、php的运行用户数组要一致,例如:
chown -R www:www /temp/thinkphp8/runtime/session
//配置权限
chmod -R 755 /temp/thinkphp8/runtime/session