本文目录导读:

Laravel的策略授权(Policy)是用于组织特定模型授权逻辑的类,我来详细讲解如何创建和使用:
创建策略
手动创建
php artisan make:policy PostPolicy
带模型创建(自动生成常用方法)
php artisan make:policy PostPolicy --model=Post
定义策略方法
<?php
namespace App\Policies;
use App\Models\User;
use App\Models\Post;
use Illuminate\Auth\Access\Response;
class PostPolicy
{
/**
* 查看列表
*/
public function viewAny(User $user)
{
return true;
}
/**
* 查看单个文章
*/
public function view(User $user, Post $post)
{
// 公开文章或作者可查看
if ($post->status === 'published') {
return true;
}
return $user->id === $post->user_id;
}
/**
* 创建文章
*/
public function create(User $user)
{
return $user->role === 'author' || $user->role === 'admin';
}
/**
* 更新文章
*/
public function update(User $user, Post $post)
{
return $user->id === $post->user_id
? Response::allow()
: Response::deny('您不能编辑别人的文章');
}
/**
* 删除文章
*/
public function delete(User $user, Post $post)
{
// 文章作者或管理员可以删除
return $user->id === $post->user_id || $user->isAdmin();
}
/**
* 批量删除
*/
public function deleteAny(User $user)
{
return $user->isAdmin();
}
/**
* 恢复软删除的文章
*/
public function restore(User $user, Post $post)
{
return $user->isAdmin();
}
/**
* 永久删除
*/
public function forceDelete(User $user, Post $post)
{
return $user->isAdmin();
}
}
注册策略
自动发现(推荐)
在 App\Providers\AuthServiceProvider 中:
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use App\Models\Post;
use App\Policies\PostPolicy;
class AuthServiceProvider extends ServiceProvider
{
/**
* 模型与策略的映射
*/
protected $policies = [
Post::class => PostPolicy::class,
// 其他模型...
];
public function boot()
{
$this->registerPolicies();
}
}
自动发现规则
Laravel 会自动发现策略,只要遵循命名规则:
- 模型在
App\Models\Post - 策略在
App\Policies\PostPolicy
使用策略授权
控制器中使用
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* 创建文章
*/
public function store(Request $request)
{
// 检查当前用户是否有创建权限
$this->authorize('create', Post::class);
// 或者使用 Gate facade
// if (!Gate::allows('create', Post::class)) {
// abort(403);
// }
// 创建文章...
}
/**
* 更新文章
*/
public function update(Request $request, Post $post)
{
// 检查当前用户是否有更新该文章的权限
$this->authorize('update', $post);
// 更新文章...
}
/**
* 删除文章
*/
public function destroy(Post $post)
{
// 检查删除权限
$this->authorize('delete', $post);
$post->delete();
return redirect()->route('posts.index');
}
}
在控制器构造函数中自动授权
class PostController extends Controller
{
public function __construct()
{
$this->authorizeResource(Post::class, 'post');
}
}
在 Blade 模板中使用
{{-- 使用 can 指令 --}}
@can('update', $post)
<a href="{{ route('posts.edit', $post) }}">编辑</a>
@endcan
{{-- 使用 cannot 指令 --}}
@cannot('delete', $post)
<p>您没有删除权限</p>
@endcan
{{-- 在表单中使用 --}}
@can('create', App\Models\Post::class)
<a href="{{ route('posts.create') }}">创建文章</a>
@endcan
{{-- 使用授权结果对象 --}}
@can('update', $post)
<form action="{{ route('posts.update', $post) }}" method="POST">
@csrf
@method('PUT')
<button type="submit">更新</button>
</form>
@elsecan('delete', $post)
<p>只有管理员可以删除</p>
@else
<p>您没有操作权限</p>
@endcan
在路由中使用
Route::middleware('can:update,post')->put('/posts/{post}', [PostController::class, 'update']);
Route::middleware('can:create,App\Models\Post')->post('/posts', [PostController::class, 'store']);
在请求验证中使用
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UpdatePostRequest extends FormRequest
{
public function authorize()
{
return $this->user()->can('update', $this->post);
}
public function rules()
{
return [
'title' => 'required|string|max:255',
'content' => 'required|string',
];
}
}
使用示例(第一段):## 完整实战示例
### 1. 创建迁移和数据模型
```php
// database/migrations/xxx_create_posts_table.php
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->string('title');
$table->text('content');
$table->enum('status', ['draft', 'published', 'archived'])->default('draft');
$table->softDeletes();
$table->timestamps();
});
// app/Models/Post.php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Post extends Model
{
use HasFactory, SoftDeletes;
protected $fillable = ['title', 'content', 'status', 'user_id'];
public function user()
{
return $this->belongsTo(User::class);
}
}
// app/Models/User.php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\Relations\HasMany;
class User extends Authenticatable
{
use HasFactory;
protected $fillable = ['name', 'email', 'password', 'role'];
protected $hidden = ['password', 'remember_token'];
public function posts(): HasMany
{
return $this->hasMany(Post::class);
}
public function isAdmin(): bool
{
return $this->role === 'admin';
}
public function isEditor(): bool
{
return $this->role === 'editor';
}
}
创建策略类
// app/Policies/PostPolicy.php
namespace App\Policies;
use App\Models\User;
use App\Models\Post;
use Illuminate\Auth\Access\Response;
class PostPolicy
{
/**
* 查看文章列表(所有登录用户可以查看)
*/
public function viewAny(User $user): bool
{
return true;
}
/**
* 查看单个文章(公开文章或作者可查看)
*/
public function view(User $user, Post $post): bool
{
if ($post->status === 'published') {
return true;
}
return $user->id === $post->user_id;
}
/**
* 创建文章(作者和管理员可以创建)
*/
public function create(User $user): bool
{
return true; // 所有登录用户都可以创建
}
/**
* 更新文章(作者本人或管理员)
*/
public function update(User $user, Post $post): Response
{
if ($user->id === $post->user_id) {
return Response::allow('您是这个文章的作者');
}
if ($user->isAdmin()) {
return Response::allow('管理员可以编辑任何文章');
}
return Response::deny('您没有权限编辑其他用户发布的文章');
}
/**
* 删除文章(作者本人或管理员)
*/
public function delete(User $user, Post $post): bool
{
return $user->id === $post->user_id || $user->isAdmin();
}
/**
* 批量删除(仅管理员)
*/
public function deleteAny(User $user): bool
{
return $user->isAdmin();
}
/**
* 恢复被删除的文章(仅管理员)
*/
public function restore(User $user, Post $post): bool
{
return $user->isAdmin();
}
/**
* 永久删除(仅管理员)
*/
public function forceDelete(User $user, Post $post): bool
{
return $user->isAdmin();
}
/**
* 发布文章(作者本人或管理员)
*/
public function publish(User $user, Post $post): bool
{
return $user->id === $post->user_id || $user->isAdmin();
}
/**
* 归档文章(仅管理员)
*/
public function archive(User $user, Post $post): bool
{
return $user->isAdmin();
}
}
注册策略
// app/Providers/AuthServiceProvider.php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
use App\Models\Post;
use App\Policies\PostPolicy;
use App\Models\User;
class AuthServiceProvider extends ServiceProvider
{
/**
* 策略映射
*/
protected $policies = [
Post::class => PostPolicy::class,
];
public function boot()
{
$this->registerPolicies();
// 定义额外的 Gate(针对不同场景)
Gate::define('manage-posts', function (User $user) {
return $user->isAdmin() || $user->isEditor();
});
}
}
控制器使用示例
// app/Http/Controllers/PostController.php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class PostController extends Controller
{
/**
* 显示文章列表
*/
public function index()
{
$posts = Post::where('status', 'published')->get();
return view('posts.index', compact('posts'));
}
/**
* 显示创建表单
*/
public function create()
{
$this->authorize('create', Post::class);
return view('posts.create');
}
/**
* 保存新文章
*/
public function store(Request $request)
{
$this->authorize('create', Post::class);
$validated = $request->validate([
'title' => 'required|string|max:255',
'content' => 'required|string',
]);
$post = Auth::user()->posts()->create($validated);
return redirect()->route('posts.show', $post)->with('success', '文章创建成功!');
}
/**
* 显示单个文章
*/
public function show(Post $post)
{
$this->authorize('view', $post);
return view('posts.show', compact('post'));
}
/**
* 显示编辑表单
*/
public function edit(Post $post)
{
$this->authorize('update', $post);
return view('posts.edit', compact('post'));
}
/**
* 更新文章
*/
public function update(Request $request, Post $post)
{
$this->authorize('update', $post);
$validated = $request->validate([
'title' => 'required|string|max:255',
'content' => 'required|string',
'status' => 'sometimes|in:draft,published,archived',
]);
$post->update($validated);
return redirect()->route('posts.show', $post)->with('success', '文章更新成功!');
}
/**
* 删除文章
*/
public function destroy(Post $post)
{
$this->authorize('delete', $post);
$post->delete();
return redirect()->route('posts.index')->with('success', '文章已删除!');
}
/**
* 发布文章(自定义操作)
*/
public function publish(Post $post)
{
$this->authorize('publish', $post);
$post->update(['status' => 'published']);
return back()->with('success', '文章已发布!');
}
}
视图中的使用
{{-- resources/views/posts/show.blade.php --}}
@extends('layouts.app')
@section('content')
<div class="container">
<h1>{{ $post->title }}</h1>
<p class="text-muted">
By {{ $post->user->name }} |
Status: {{ $post->status }} |
Created: {{ $post->created_at->diffForHumans() }}
</p>
<div class="mt-4">
{{ $post->content }}
</div>
{{-- 使用 @can 指令判断按钮显示 --}}
<div class="mt-4">
{{-- 编辑按钮(当前用户是作者或管理员) --}}
@can('update', $post)
<a href="{{ route('posts.edit', $post) }}" class="btn btn-primary">编辑</a>
@endcan
{{-- 发布按钮(当前用户是作者或管理员) --}}
@can('publish', $post)
@if($post->status === 'draft')
<form action="{{ route('posts.publish', $post) }}" method="POST" class="d-inline">
@csrf
<button type="submit" class="btn btn-success">发布</button>
</form>
@endif
@endcan
{{-- 删除按钮 --}}
@can('delete', $post)
<form action="{{ route('posts.destroy', $post) }}" method="POST" class="d-inline">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger" onclick="return confirm('确定删除吗?')">删除</button>
</form>
@endcan
</div>
{{-- 错误提示 --}}
@can('update', $post)
{{-- 有权限显示的内容 --}}
@elsecan('publish', $post)
{{-- 有发布权限的内容 --}}
@else
<p class="alert alert-warning">您没有权限编辑这篇文章</p>
@endcan
</div>
@endsection
自定义授权消息和响应
// 在策略方法中使用 Response 类自定义错误消息
public function update(User $user, Post $post): Response
{
if ($user->id === $post->user_id) {
return Response::allow();
}
return Response::denyWithStatus(403, '您不能编辑其他人的文章');
// 或
// return Response::deny('自定义错误消息', 403);
}
// 使用 Gate 检查
if (Gate::allows('update', $post)) {
// 允许
}
if (Gate::denies('update', $post)) {
// 拒绝
}
// 检查当前用户
if ($request->user()->can('update', $post)) {
// 允许
}
if ($request->user()->cannot('update', $post)) {
// 拒绝
}
// 对于管理操作
if ($user->can('update', $post)) {
// 有更新权限
}
// 抛出自定义错误
if (!$user->can('update', $post)) {
throw new AuthorizationException('您没有权限执行此操作');
}
// 使用 middleware
Route::put('/posts/{post}', [PostController::class, 'update'])
->middleware('can:update,post');
通过以上示例,你可以看到 Laravel 策略授权提供了灵活且强大的权限控制能力,根据具体需求,你可以自定义更多的授权方法,用于精细化的权限管理。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播