HTTP 协议是无状态的,这意味着每次请求之间是独立的。为了在多个请求之间保持用户数据(如登录状态、购物车内容),我们需要使用 Session(会话)。Laravel 提供了统一的 Session API,支持多种后端驱动(文件、Redis、数据库、Cookie 等),让你可以灵活地存储和读取用户状态。
Session 配置文件位于 config/session.php。默认驱动可以通过 .env 中的 SESSION_DRIVER 设置。Laravel 支持以下驱动:
| 驱动 | 说明 | 适用场景 |
|---|---|---|
file | 将 Session 存储在 storage/framework/sessions 目录。 | 小型项目、开发环境 |
cookie | 将加密的 Session 数据直接存储在客户端 Cookie 中(4KB 限制)。 | 极简应用,无需服务端存储 |
database | 使用数据库表存储 Session,需运行 php artisan session:table。 | 中等规模、无 Redis |
redis | 基于 Redis,高性能,适合分布式环境。 | 生产环境首选 |
memcached | 基于 Memcached,极高读写速度。 | 对速度要求极高 |
array | 仅当前请求有效,用于测试。 | 单元测试 |
.env 配置示例(Redis)
SESSION_DRIVER=redis
SESSION_LIFETIME=120 # 分钟
SESSION_CONNECTION=default # Redis 连接名
使用数据库驱动时,需先生成迁移表并执行迁移:
php artisan session:table
php artisan migrate
通过 Session Facade 或全局辅助函数 session() 可以轻松存取数据。
use Illuminate\Support\Facades\Session;
// 使用 Facade
Session::put('key', 'value');
Session::put(['key1' => 'value1', 'key2' => 'value2']);
// 如果键不存在则存储
Session::add('key', 'default');
// 推入数组
Session::push('user.teams', 'developers');
// 辅助函数
session(['key' => 'value']);
$value = Session::get('key');
$value = Session::get('key', 'default');
$value = Session::get('key', function () {
return 'default';
});
// 获取所有数据
$all = Session::all();
// 判断是否存在
if (Session::has('users')) { ... }
if (Session::exists('users')) { ... } // 即使值为 null 也返回 true
// 获取并删除
$value = Session::pull('key', 'default');
Session::forget('key'); // 删除单个
Session::forget(['key1', 'key2']);
Session::flush(); // 清空所有 Session 数据
出于安全考虑(防止 Session Fixation 攻击),在用户登录后应重新生成 Session ID:
Session::regenerate();
有时你希望在下一个请求结束后自动删除某些数据,例如操作成功提示消息。闪存数据正是为此设计的。
// 存储闪存数据(仅下一次请求有效)
Session::flash('status', '任务成功!');
// 重新闪存以延长到再下一次请求
Session::reflash();
// 只保留部分闪存数据
Session::keep(['username', 'email']);
// 现在(当前请求)也可以获取闪存数据
$status = Session::get('status');
你可以在视图中直接获取 Session 数据,例如显示错误消息:
@if (session('status'))
<div class="alert alert-success">
{{ session('status') }}
</div>
@endif
如果需要使用非内置的存储系统(如 MongoDB),可以扩展 Session 系统。在服务提供者中调用 Session::extend() 方法。
namespace App\Providers;
use Illuminate\Support\Facades\Session;
use App\Extensions\MongoSessionHandler;
class SessionServiceProvider extends ServiceProvider
{
public function boot()
{
Session::extend('mongo', function ($app) {
return new MongoSessionHandler;
});
}
}
然后更新 .env 中的 SESSION_DRIVER=mongo。
Session::regenerate() 防止会话固定攻击。SESSION_LIFETIME 单位为分钟,根据业务需求调整(如记住我功能可延长)。session.secure 设置为 true,确保 Cookie 仅通过 HTTPS 传输。
// 在 routes/console.php 中
Schedule::command('session:gc')->daily();
默认情况下,Laravel 会为每个请求自动启动 Session(除非你配置了 start_session 中间件)。你可以通过以下方式手动控制:
// 启动 Session
Session::start();
// 保存 Session 数据(通常在请求结束自动调用)
Session::save();
Laravel 的 Session 系统为无状态的 HTTP 协议提供了强大的状态管理能力。通过配置合适的驱动,你可以轻松存储用户状态,并利用闪存数据实现一次性提示。掌握 Session 的基本操作和安全注意事项,是构建任何需要用户交互的 Web 应用的基础。