Laravel 授权实战:用 Policy 与 Gate 把权限判断收口到一处
test12026-09-303 次阅读
为什么要把授权收口
权限判断如果散落在控制器、模板、服务里,规则一变就要到处改,还容易漏。Laravel 提供 Gate 和 Policy 两套机制,把「当前用户能不能做这件事」集中定义,调用方只管问一句 authorize,通过才继续,否则自动抛 403。
用 Gate 注册闭包式授权
简单场景用 Gate 在服务提供者里注册一个闭包即可,第一个参数是当前用户,后面是业务参数。
// app/Providers/AppServiceProvider.php
use App\Models\Post;
use Illuminate\Support\Facades\Gate;
public function boot(): void
{
Gate::define('update-post', function ($user, Post $post) {
return $user->id === $post->user_id;
});
}
用 Policy 绑定模型
模型相关的授权更适合写成 Policy,一个模型一套方法,可读性更好。用 artisan 命令生成并绑定模型。
// php artisan make:policy PostPolicy --model=Post
namespace App\Policies;
use App\Models\Post;
use App\Models\User;
class PostPolicy
{
public function update(User $user, Post $post): bool
{
return $user->id === $post->user_id;
}
public function delete(User $user, Post $post): bool
{
return $user->is_admin || $user->id === $post->user_id;
}
}
在控制器里使用
控制器里一行 authorize 就能挡住越权请求,未通过会直接抛出 AuthorizationException(框架转成 403)。
public function update(Request $request, Post $post)
{
$this->authorize('update', $post); // 不通过直接抛 403
// 通过后再执行业务逻辑
$post->update($request->validated());
return redirect()->back();
}
在模板里做条件渲染
Blade 提供了 @can 指令,让用户只能看到自己有权限操作的按钮,避免「点了才报错」的体验。
@can('delete', $post)
<button>删除</button>
@endcan
几点注意
- Gate 适合与具体模型无关的通用能力,Policy 适合绑定到某个模型的细粒度操作。
- authorize 第二个参数传模型实例,Laravel 会自动解析出对应的 Policy。
- 管理员兜底逻辑写在 Policy 里比写在控制器更统一,避免每个方法都单独判断。
- API 场景下用 abort(403) 或异常处理器统一返回 JSON 错误体,不要让前端拿到整页错误。
T
test1
文章作者
为什么要把授权收口 权限判断如果散落在控制器、模板、服务里,规则一变就要到处改,还容易漏。Laravel 提供 Gat...
- 分类
- 技术
- 发布时间
- 2026-09-30
- 字数
- 约 1510 字
- 阅读
- 3 次
