Laravel Session 问题核心在于驱动匹配环境:array驱动仅测试用、cookie超4KB或HTTPS未设secure致失效;Redis驱动需正确配置连接与扩展;regenerate()防会话固定,migrate()仅换ID;自定义驱动须规范实现read/write/gc且注入ConnectionInterface。
Session 在 Laravel 中默认可用,但实际项目中常因配置不当、驱动误选或生命周期理解偏差导致数据存不住、跨请求丢失、测试环境失效等问题。核心判断标准只有一条:你用的驱动是否匹配当前部署环境与需求。
session()->put() 存了却读不到?最常见原因是会话未启动或驱动不支持当前上下文:
php artisan serve 启动时若未启用 session_start()(Laravel 通常自动处理,但中间件顺序错乱可能跳过)
array 驱动(默认仅用于测试)——它不持久化,每次请求都是新数组cookie 驱动但数据超 4KB,浏览器截断导致解密失败,session()->get() 返回 null
'secure' => true,而 Cookie 被浏览器拒绝发送验证方式:在路由闭包中加
dd(session()->getId(), session()->isStarted());,若 ID 为空或
isStarted() 为 false,说明会话根本没激活。
redis 驱动并避免连接失败?Redis 是生产推荐驱动,但配置疏漏会导致整个应用 500 错误:
config/session.php 中 'driver' => 'redis',且 'connection' 值与 config/database.php 的 redis.default 名称一致predis/predis 或 phpredis 扩展;Laravel 10+ 默认用 phpredis,若未启用扩展会静默回退到 file 驱动(日志里无报错但行为异常)'options' => [
'connection_timeout' => 1,
'read_write_timeout' => 1,
]laravel_session:,如需隔离多应用,请改 'prefix' 配置项,避免键冲突session()->regenerate() 和 session()->migrate() 该用哪个?二者都重置 Session ID,但语义和适用场景不同:
session()->regenerate():销毁旧 session 数据,生成新 ID,适用于登录成功后防会话固定(Session Fixation)。它会保留当前已 put() 的数据session()->migrate():仅更换 ID,不销毁原数据,旧 ID 对应的数据仍可被读取(直到过期),安全性弱于 regenerate()
StartSession 之后,否则无效典型登录后操作:
Auth::login($user); session()->regenerate(true); // true 表示删除旧 session 文件(对 file/redis 驱动有效)
实现 SessionHandlerInterface 不难,但以下三点不处理就会“存得进、取不出”:
read($id) 必须返回字符串,哪怕空也要返回 '',返回 null 或 false 会被 Laravel 当作“会话不存在”,直接新建一个write($id, $data) 中的 $data 是 PHP 序列化后的字符串(含 | 分隔符),不要二次 serialize(),否则解码失败gc($maxLifetime),否则自定义驱动不会触发垃圾回收,过期 session 永远堆积另外,Laravel 9+ 强制要求自定义驱动类注册时传入 ConnectionInterface 实例(如数据库连接),不能直接 new PDO —— 否则无法参与连接池和事务上下文。