Laravel 中 Gates 与 Middleware 的核心区别解析

gates 用于授权(判断“用户能否执行某操作”),middleware 用于请求过滤(拦截并处理 http 请求,如认证、日志、cors 等);二者职责分离、互不包含,可协同使用但无嵌套关系。

在 Laravel 中,GateMiddleware 是两个独立且正交的概念,常被初学者混淆,尤其当两者都涉及“用户访问控制”时。关键在于:它们解决的是不同层面的问题——Middleware 处理请求生命周期,Gate 处理业务逻辑授权

✅ Middleware:请求管道的“守门员”

Middleware 运行在 HTTP 请求进入应用后的早期阶段(或响应返回前),对整个请求-响应周期进行干预。它不关心具体业务动作,只关注请求本身是否合规。例如:

  • auth 中间件检查请求是否携带有效认证凭证(如 session 或 token),若未登录则重定向至 /login;
  • verified 中间件确保用户邮箱已验证;
  • 自定义中间件可记录请求日志、限制 API 频率、强制 HTTPS 等。
// app/Http/Middleware/CheckAge.php
public function handle(Request $request, Closure $next)
{
    if ($request->age < 18) {
        return redirect('adults-only');
    }
    return $next($request);
}

⚠️ 注意:Middleware 不具备用户行为细粒度判断能力——它无法回答“当前用户能否删除这篇博客?”这类问题,因为它通常不加载完整用户模型或业务上下文。

✅ Gate(及 Policy):业务授权的“裁判员”

Gate 是 Laravel 的授权机制,专为“某用户是否被允许执行某操作”而设计。它基于用户实例、资源和动作三元组进行动态判断,支持闭包定义或 Policy 类封装:

// 定义 Gate(app/Providers/AuthServiceProvider.php)
Gate::define('delete-post', function (User $user, Post $post) {
    return $user->id === $post->user_id || $user->role === 'admin';
});

// 控制器中使用
if (Gate::allows('delete-post', $post)) {
    $post->delete();
} else {
    abort(403);
}

或配合 Policy 实现更清晰的授权逻辑:

// 调用策略方法(自动解析)
$this->authorize('delete', $post); // 触发 PostPolicy@delete()

✅ Gate 的优势在于:支持资源绑定、依赖注入、策略复用,并天然适配 Blade 指令(@can('update', $post))和 JSON API 响应。

❌ 它们不是包含关系

Middleware 不包含 Gate,Gate 也不属于 Middleware。你不能在中间件里“调用 Gate”来实现登录跳转——因为未认证用户根本拿不到 $user 实例,Gate::allows() 将抛出异常或返回 false,但这并非其设计目的。正确的做法是:

  • ✅ 用 auth 中间件保障路由级访问(如 middleware('auth'));
  • ✅ 在控制器或服务层用 Gate::allows() 或 $this->authorize() 执行操作级授权。

? 协同工作示例

一个典型的博客编辑页可能这样组合使用:

// routes/web.php
Route::get('/posts/{post}/edit', [PostController::class, 'edit'])
    ->middleware('auth')           // 第一层:必须登录
    ->can('update', 'post');       // ⚠️ 注意:这是 Laravel 9+ 的「授权中间件」语法(底层仍调用 Gate)

// PostController.php
public function update(Request $request, Post $post)
{
    $this->authorize('update', $post); // 第二层:校验该用户能否更新此文章
    $post->update($request->validated());
}
? 提示:->can('update', 'post') 是 Laravel 提供的便捷授权中间件语法,它内部调用 Gate,但本质仍是 Middleware 层的快捷注册方式——它并未让 Gate “嵌入” Middleware,而是桥接二者。

总结

维度 Middleware Gate / Policy
核心目标 过滤/修改请求或响应 判断用户是否有权执行特定操作
执行时机 请求进入/响应发出时(全局) 业务逻辑中按需调用(局部)
依赖上下文 Request、Response、Closure User 实例、资源模型、动作字符串
典型用途 认证、日志、CORS、CSRF 权限控制、角色判断、多租户隔离
是否可替代 ❌ 不能替代 Gate 的细粒度授权 ❌ 不能替代 Middleware 的请求拦截

理解这一区分,是构建安全、可维护 Laravel 应用的关键基础。