Session 突然失效主因是 file 驱动在生产环境因权限、共享存储或 CLI 场景写入失败;应切换 database 或 redis 驱动,并检查权限、配置、GC 机制与 Cookie 属性协同问题。

Session 为什么突然失效?先看 Laravel 的默认配置
Laravel 默认使用 file 驱动保存 Session,看似简单,但实际在共享主机、多服务器、CLI 命令或 Nginx + PHP-FPM 权限不一致时,极易因写入失败导致 Session 无法持久化——你没改过代码,但用户频繁掉登录,大概率是这个原因。
验证方法:打开 storage/framework/sessions/ 目录,手动创建一个测试文件(如 touch test.txt),如果报 Permission denied,说明 PHP 进程无权写入该目录,file 驱动必然失效。
- 检查
storage/和bootstrap/cache/目录权限是否为 755 或 775,属主是否与 PHP-FPM 用户(如www-data或nginx)一致 - 运行
php artisan storage:link并不解决 Session 写入问题,它只影响public/storage符号链接 - 开发环境用
file可以,但只要部署到生产环境,尤其用了负载均衡或 Docker,必须换驱动
切换到 database 驱动:比 file 更稳,且支持跨机器
database 驱动把 Session 存进数据库,天然规避文件权限和共享存储问题,适合绝大多数中小项目。但它不是开箱即用,漏掉一步就会报 Class 'CreateSessionsTable' not found 或 Session 完全不写入。
- 执行
php artisan session:table生成迁移文件(注意:不是make:migration) - 确认
config/session.php中'driver' => 'database',且'connection' => null(使用默认数据库连接) - 确保
session表的payload字段是text类型(MySQL)或longtext(否则大 Session 会截断) - 若用 MySQL 8.0+,避免在
session表上设utf8mb4_unicode_ci以外的 collation,否则可能因字符集不兼容导致写入静默失败
设置过期时间别只改 lifetime:还要看垃圾回收和浏览器行为
很多人以为改了 config/session.php 中的 'lifetime' => 120(单位分钟),Session 就真能活 2 小时,但实际常出现“刚登录就退出”或“关浏览器再开还登录着”——这是混淆了服务端过期、客户端 Cookie 过期、以及 GC 触发机制。
-
'lifetime'控制的是服务端 Session 数据的生存时间(从最后活动时间起算),但前提是 PHP 的 Session GC 被触发;Laravel 默认每 100 次请求有 1% 概率清理过期项,低流量站点可能几小时都不清理 -
'expire_on_close' => false是关键:设为true时,浏览器关闭后 Cookie 自动销毁,下次打开就是新 Session;设为false(默认),则依赖'lifetime'和 Cookie 的expires属性 - Cookie 的
expires时间由'lifetime'* 60 秒推算得出,但若前端 JS 调用document.cookie手动设置了无expires的 Session Cookie,它就成了“会话 Cookie”,关浏览器即失效——和 Laravel 配置无关
Redis 驱动踩坑:连接池、序列化、以及 Laravel 版本差异
高并发场景推荐 redis 驱动,但它对 Redis 配置更敏感。常见现象是本地 OK,上生产就报 Connection refused 或 Session 读取为空。
- 确认
config/database.php中redis配置的'host'不是localhost(Docker 环境下应为容器名如redis),且'port'和'password'匹配 - Laravel 9+ 默认用
phpredis扩展,若只装了predis,需在config/database.php的 redis 配置里显式加'client' => 'predis' - Redis 默认不启用序列化,而 Laravel Session 使用
serialize(),若 Redis 实例被其他语言程序共用,且清空过数据,可能残留非 PHP 序列化格式内容,导致解包失败——建议为 Session 单独建 Redis DB(如'database' => 1) - 不要在
.env里写REDIS_URL=redis://:pass@127.0.0.1:6379/0同时又在database.php里填 host/port,Laravel 会优先用 URL,忽略其他字段,容易配错
Session 失效很少是单一配置问题,往往是驱动、权限、GC、Cookie 属性、网络连通性这五者中某两个叠加出问题。调的时候别只盯 config/session.php,先用 dd(session()->getId()) 和日志查 ID 是否每次刷新都变,再逐步排除。










