上线每个 Laravel 项目都会装上的七个安全包
2026 年的 Laravel 应用如果还是"之后再加固吧",基本等于在排队安排一场事故。安全早已不只是密码和 CSRF 的事——它是分层防御、可审计的痕迹、持续监控三件事一起做。
好消息是,Laravel 本身的默认值已经相当稳(CSRF、密码哈希、授权、预编译语句),过去两年周边生态也成熟了不少。靠几个经过战场验证的包,就能在不写一大堆自定义代码的前提下,非常接近 OWASP 风格的生产级安全态势。
本文会逐个介绍几乎每个现代 Laravel 项目都会装上的安全类包,以及它们为什么重要、如何落到真实项目中。
1. 用 Sanctum 与 Passport 先把鉴权做对
在往上堆花哨的安全组件之前,先要把认证这层做扎实。Laravel 给了两种一等选择:Sanctum 和 Passport。
- Laravel Sanctum 适合 SPA、移动端、以及简单的 token 化 API。
- Laravel Passport 是完整的 OAuth 2 服务器实现,支持 OAuth 2.1 流程和 Authorization Code + PKCE 等高级 grant。
Laravel 官方文档的态度很明确:如果没有真正需要 OAuth 2 的场景(例如必须和你 API 集成的第三方客户端或 MCP 服务器),优先 Sanctum。
何时选哪一个
选 Sanctum:
- 前端在自己手里(Inertia、Vue、React、移动 App)。
- 需要的是基于 cookie 的 SPA 鉴权,或简单的个人访问 token。
选 Passport:
- 要对外公开 API,服务第三方客户端。
- 需要一等公民的 OAuth 2.1 流程,包括 PKCE 与 device code grant。
两者都接入 Laravel 的 guard、policy 与中间件,所以授权仍可以继续用 gate 或 Spatie Permission 等包在上面叠。
Sanctum + Policy 的一个例子
一条用 Sanctum 保护、同时仍走 policy 做细粒度权限判断的路由:
// routes/api.php
use App\Models\Post;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::middleware(['auth:sanctum'])->group(function () {
Route::patch('/posts/{post}', function (Request $request, Post $post) {
$request->user()->canOrFail('update', $post);
$validated = $request->validate([
'title' => ['sometimes', 'string', 'max:255'],
'body' => ['sometimes', 'string'],
]);
$post->update($validated);
return response()->json($post);
});
});这里 Sanctum 回答"你是谁",policy 回答"你有没有权限做这件事"——正是 Laravel 安全模型本身的分工。
2. 用 Spatie Laravel Permission 把 RBAC 做稳
用户能登录后,下一块攻击面就是授权。把 is_admin 类检查硬编码在代码里既不好扩展,需求一变就彻底翻车。
在 Laravel 世界里做 RBAC 事实标准的包是 spatie/laravel-permission。它把角色与权限放进数据库,并无缝接进 Laravel 的 Gate,使得控制器和 Blade 里仍可以继续用熟悉的 can 检查。
几乎每一份"常用包"清单里它都会出现,生产与学术项目都在用,几条关键理由:
- 数据库承载角色与权限。
- 与 Laravel 的 Gate、
canAPI 自然集成。 - 与 Sanctum 的 token 鉴权配合良好。
基础配置
装好包并执行完迁移之后,在 User 上加 trait:
// app/Models/User.php
use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasRoles;
// ...
}播种一些角色与权限:
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
$admin = Role::create(['name' => 'admin']);
$editor = Role::create(['name' => 'editor']);
Permission::create(['name' => 'posts.view']);
Permission::create(['name' => 'posts.update']);
$admin->givePermissionTo(['posts.view', 'posts.update']);
$editor->givePermissionTo('posts.view');在控制器里搭配 policy 或直接走 gate:
public function update(PostRequest $request, Post $post)
{
$this->authorize('update', $post); // 走 Laravel policy
// 或者直接做权限检查
abort_unless($request->user()->can('posts.update'), 403);
$post->update($request->validated());
return redirect()->route('posts.show', $post);
}许多真实研究项目和生产应用用的就是 Sanctum + Spatie Permission 的组合:在 API 层叠加速率限制、角色、token scope 等多层约束,滥用风险会显著下降。
3. 用 NoCaptcha 把机器人挡在门外
即使鉴权做得稳,一个简单的"注册账户"表单也可能变成刷账号、耗资源、撞库的入口。必须在门口就挡一道。
Laravel 里最常用的 Google reCAPTCHA 集成是 anhskohbo/no-captcha。它把服务端校验与 Blade 辅助方法一起封好,基本上加几行就能上到任意表单。
典型场景:
- 注册与密码重置表单。
- "联系我们"、工单表单。
- 修改邮箱、删除账户等高风险操作。
注册表单加 reCAPTCHA 示例
控制器侧的校验:
// app/Http/Controllers/Auth/RegisterController.php
use Anhskohbo\NoCaptcha\Facades\NoCaptcha;
public function store(Request $request)
{
$validated = $request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'email', 'max:255'],
'password' => ['required', 'confirmed', 'min:12'],
'g-recaptcha-response' => ['required', 'captcha'],
]);
// 创建用户...
}Blade 模板:
<form method="POST" action="{{ route('register') }}">
@csrf
<!-- name、email、password 字段 -->
{!! NoCaptcha::display() !!}
@error('g-recaptcha-response')
<p class="text-red-600 text-sm">{{ $message }}</p>
@enderror
<button type="submit">Create account</button>
</form>
{!! NoCaptcha::renderJs() !!}单这一步就能砍掉可观的自动化滥用,同时把用户体验伤害压到可以接受。
4. 用 Laravel Disposable Email Detection 屏蔽一次性邮箱
一次性邮箱服务让"注册即弃"的账号几乎免费——绕过邮箱验证、绕过封号名单都变得毫无成本。对涉及计费、限流 API 或社区功能的应用来说,把这类账号放进来就是一场持续的反滥用灾难。
eramitgupta/laravel-disposable-email 这个包就是来管这件事的,自带一份超过 10 万条已知一次性邮箱域名的清单,并作为 Laravel 校验规则使用。
它能做的事:
- 注册时用校验规则直接拒绝一次性邮箱。
- 在用户改资料或高风险操作时做运行时复检。
注册时拒绝一次性邮箱示例
// app/Http/Requests/RegisterRequest.php
use Illuminate\Foundation\Http\FormRequest;
class RegisterRequest extends FormRequest
{
public function rules(): array
{
return [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'email', 'max:255', 'unique:users', 'not_disposable_email'],
'password' => ['required', 'confirmed', 'min:12'],
];
}
}其中 not_disposable_email 就是包里自带的规则,会把域名与内置的 10 万 + 一次性邮箱清单做比对。
和 reCAPTCHA 搭着用,既能大幅抬高攻击者批量注册的成本,代码又不会膨胀。
5. 用 owen-it/laravel-auditing 记录每一次变更
生产出问题时,团队(或客户)最先问的基本都是"谁、什么时候、改了什么"。一条稳固的审计线索是事故响应、排障、合规检查的共同基础。
owen-it/laravel-auditing 是 Laravel/Lumen 领域最成熟、最久经验证的模型变更追踪方案之一。它会自动记录 created、updated、deleted、restored 这些事件,同时保存变更前后的属性值,附带 URL、IP、User-Agent、Tag 等上下文元数据。
它在 2026 年的 Laravel 安全栈里仍然站得住脚,几条理由:
- 只要给模型加一个 trait 和一个接口就启用审计,无需大范围重构。
- 留存的是随时间流动的变更历史,方便回溯谁在何时改过什么。
- 哪些字段要审计、哪些要隐去、审计要打哪个 tag(例如
security、billing)都可按业务定制。
基础接入示例
按官方文档用 Composer 安装并发布配置,把需要审计的模型标记成可审计:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use OwenIt\Auditing\Contracts\Auditable as AuditableContract;
use OwenIt\Auditing\Auditable;
class Post extends Model implements AuditableContract
{
use Auditable;
protected $fillable = [
'title',
'body',
'status',
];
// 可选:只审计指定属性或事件
protected $auditInclude = ['title', 'body', 'status'];
}之后每当 Post 被创建、更新、删除或恢复,Laravel Auditing 都会往 audits 表写入一条记录:包含事件名、改动 diff、当前责任用户(可获取时)、以及上下文元数据。
再在后台面板上暴露一份简单的审计流,或为用户、发票、配置这类敏感实体做一个独立的"活动"标签,既给团队提供了可疑变更的可见性,也方便满足合规 checklist。
6. 把备份当成安全特性,用 spatie/laravel-backup
备份通常被归在 DevOps 或 SRE 之下,但从攻击者视角,一份可靠的备份是最后一道防线。勒索软件、误删、管理员账号被盗,只要能快速恢复,伤害都会显著减弱。
spatie/laravel-backup 多年来都是社区常驻包,2025–2026 的"必装包"清单里仍然反复出现。它能:
- 对数据库与指定目录做压缩备份。
- 写到任意 Laravel 文件系统盘(S3、Dropbox 等)。
- 监控备份健康度,备份失败或过期时通知到团队。
计划任务示例
配好磁盘后,把备份接入 Laravel 的调度器:
// app/Console/Kernel.php
use Illuminate\Console\Scheduling\Schedule;
class Kernel extends ConsoleKernel
{
protected function schedule(Schedule $schedule): void
{
$schedule->command('backup:run')
->dailyAt('02:00')
->onOneServer()
->withoutOverlapping();
$schedule->command('backup:monitor')
->dailyAt('03:00');
}
}再把通知(Slack、邮件等)配上,备份失败时第一时间能听到。许多"必装包"清单都把它点名为生产 Laravel 应用的核心韧性组件。
7. 持续扫描与监控,使用 Aikido 与 Nightwatch
就算鉴权、RBAC、CAPTCHA、备份都到位,应用的安全态势也不是静止的。每周都有新的 CVE 落地,依赖会老化,配置会被无意改坏。
这就是安全扫描与监控该出场的位置。
Aikido:和 Laravel Forge 集成的漏洞扫描
Laravel 与 Aikido 有官方集成,针对通过 Forge 部署的 Laravel 应用做安全扫描,能力包括:
- 扫描代码与依赖中的已知漏洞(含第三方包)。
- 把发现的问题直接呈现在 Forge 中,让团队赶在被利用之前打补丁。
对独立开发者和小团队,这是一条相当划算的路:拿到一套安全工具,不必自己维护扫描器。
Nightwatch:注重合规的可观测性
Laravel Nightwatch 是 Laravel 一方监控平台,提供日志、性能、错误的深度洞察,并已通过 SOC 2 Type 1 合规。这意味着:
- 监控与日志数据在经过审计的安全控制下被处理。
- 可以把结构化日志、请求、任务以及与安全相关的事件集中到一处。
主流安全实践指南反复强调:日志、监控与告警是早发现攻击、事后举证的关键。Nightwatch 给 Laravel 团队提供的就是一条注重安全的、开箱即用的实现路径。
把它们组合起来,搭一套"安全优先"的 Laravel 栈
没有任何单个包能让一个应用变得安全。安全的本质是纵深防御:把多个控制点叠在一起,单点失守也不至于毁掉整周。
下面是一份在 2026 年新项目中适用的实用基线。
框架自身的卫生
- 紧跟 Laravel 与 PHP 主版本更新;Laravel 13 通过
PreventRequestForgery中间件强化了请求伪造防护。 - 生产环境保持
APP_DEBUG=false,永远不要让密钥泄漏到日志里。
鉴权与授权
- SPA / 移动端用 Sanctum;必须支持 OAuth 2.1(含 PKCE)时上 Passport。
- 用 Spatie Laravel Permission 实现 RBAC,再以 policy 与 gate 收口。
在边界处做反滥用
- 公开的高风险表单挂 NoCaptcha。
- 用 Laravel Disposable Email Detection 拒收一次性邮箱。
- 加上速率限制与严格的校验规则,缓解暴力破解与注入攻击。
可观测性与韧性
- 用审计日志包记录模型级变更。
- 通过
spatie/laravel-backup跑计划备份、监控备份健康,并定期演练恢复。 - 在 Forge 上启用 Aikido 扫描,把应用日志和指标送进 Nightwatch 做安全的统一监控。
这套组合与现代 Laravel 安全指南、OWASP 风格建议彼此对齐:校验一切、最小权限、强审计与日志、持续扫描。