本文目录导读:

在Laravel中,表单请求授权检查主要通过Form Request类来实现,以下是详细的实现方式:
创建Form Request类
php artisan make:request StorePostRequest
基本授权检查
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StorePostRequest extends FormRequest
{
/**
* 确定用户是否有权执行此请求
*/
public function authorize(): bool
{
// 方式1:返回true表示允许所有用户
return true;
// 方式2:基于认证用户
return auth()->check();
// 方式3:基于用户角色
return auth()->user()->hasRole('admin');
// 方式4:基于模型所有权
$post = $this->route('post');
return $post && $this->user()->can('update', $post);
}
/**
* 获取应用于请求的验证规则
*/
public function rules(): array
{
return [
'title' => 'required|string|max:255',
'content' => 'required|string',
'category_id' => 'required|exists:categories,id',
];
}
/**
* 配置验证器实例
*/
public function withValidator($validator)
{
$validator->after(function ($validator) {
if ($this->input('title') === 'forbidden') {
$validator->errors()->add('title', '该标题不允许使用');
}
});
}
/**
* 自定义错误消息
*/
public function messages(): array
{
return [
'title.required' => '标题不能为空',
'title.max' => '标题不能超过255个字符',
'content.required' => '内容不能为空',
];
}
/**
* 自定义属性名称
*/
public function attributes(): array
{
return [
'title' => '文章标题',
'content' => '文章内容',
];
}
}
在控制器中使用
<?php
namespace App\Http\Controllers;
use App\Http\Requests\StorePostRequest;
use App\Models\Post;
class PostController extends Controller
{
public function store(StorePostRequest $request)
{
// 请求已经通过授权和验证
$validated = $request->validated();
$post = Post::create($validated);
return redirect()->route('posts.show', $post);
}
public function update(UpdatePostRequest $request, Post $post)
{
// 如果授权失败,会自动返回403或重定向
$post->update($request->validated());
return redirect()->route('posts.show', $post);
}
}
高级授权模式
基于策略(Policy)
// 创建UpdatePostRequest
class UpdatePostRequest extends FormRequest
{
public function authorize(): bool
{
$post = $this->route('post');
// 使用Policy进行授权
return $this->user()->can('update', $post);
}
public function rules(): array
{
return [
'title' => 'sometimes|string|max:255',
'content' => 'sometimes|string',
];
}
}
基于Gate
class UpdatePostRequest extends FormRequest
{
public function authorize(): bool
{
$post = $this->route('post');
// 使用Gate
return Gate::allows('update-post', $post);
}
}
自定义授权失败响应
class StorePostRequest extends FormRequest
{
public function authorize(): bool
{
return $this->user()->isSubscribed();
}
/**
* 授权失败的自定义响应
*/
protected function failedAuthorization()
{
if ($this->expectsJson()) {
throw new HttpResponseException(
response()->json([
'message' => '您没有权限执行此操作',
'status' => 403
], 403)
);
}
abort(403, '您没有权限执行此操作');
}
}
路由模型绑定结合
// 路由定义
Route::put('/posts/{post}', [PostController::class, 'update'])->name('posts.update');
// FormRequest中使用
class UpdatePostRequest extends FormRequest
{
public function authorize(): bool
{
// 通过route方法获取模型实例
$post = $this->route('post');
// 检查用户是否是该文章的创建者
return $post->user_id === $this->user()->id;
}
public function rules(): array
{
// 可以基于模型状态动态生成规则
$post = $this->route('post');
$rules = [
'title' => 'required|string|max:255',
'content' => 'required|string',
];
if ($post->status === 'published') {
$rules['title'] .= '|unique:posts,title,' . $post->id;
}
return $rules;
}
}
使用中间件进行基础授权
// 在控制器中使用中间件
class PostController extends Controller
{
public function __construct()
{
// 只有认证用户可以访问
$this->middleware('auth');
// 只有admin角色可以访问
$this->middleware('role:admin')->only('destroy');
// 验证post所有权
$this->middleware('can:update,post')->only(['update', 'edit']);
}
}
前端错误处理
{{-- Blade模板示例 --}}
@if($errors->any())
<div class="alert alert-danger">
<ul>
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
{{-- 单个字段错误 --}}
<input type="text" name="title" value="{{ old('title') }}">
@error('title')
<span class="text-danger">{{ $message }}</span>
@enderror
测试授权
class PostRequestTest extends TestCase
{
public function test_user_can_create_post()
{
$user = User::factory()->create();
$response = $this->actingAs($user)
->post('/posts', [
'title' => 'Test Post',
'content' => 'Post content'
]);
$response->assertSessionHasNoErrors();
$response->assertRedirect();
}
public function test_unauthorized_user_cannot_create_post()
{
$response = $this->post('/posts', [
'title' => 'Test Post',
'content' => 'Post content'
]);
$response->assertForbidden();
}
}
最佳实践建议
- 单一职责:每个FormRequest只处理一个请求场景
- 授权与验证分离:
authorize()只负责权限,rules()只负责验证 - 复用性:将通用的授权逻辑提取到Policy或Gate中
- 错误处理:提供友好的中文错误消息
- 安全考虑:永远不要信任客户端数据,始终服务端验证
这样配置后,Laravel会自动处理授权失败的情况,返回403错误和验证失败消息。