Laravel 11中Policy自动注册失效及403权限问题排查
Laravel Policy 403未授权问题排查与修复
问题描述
我正在为Todo模型创建Policy实现用户角色授权,给create()、update()等方法设置自定义权限。按照Laravel文档,我执行了php artisan make:policy todoPolicy --model=todo命令创建Policy,且Policy命名符合「模型名+Policy」规则、放在App\Policies目录下,理论上Laravel会自动注册。但测试时,我在todoPolicy的create()方法中返回true,并在Livewire组件的add方法调用$this->authorize('create', $todo);,始终得到403未授权页面,手动注册Policy也无效。
组件/控制器代码
namespace App\Livewire\Elements\Todolist; use Livewire\Component; use App\Models\todo; class Todolist extends Component { public $description; public function done($id) { sleep(0.5); todo::where('id',$id)->first()->update([ 'is_done' => true, ]); } public function restore($id) { sleep(0.5); todo::where('id',$id)->first()->update([ 'is_done' => false, ]); } public function delete($id) { sleep(0.5); todo::where('id',$id)->first()->delete(); } public function add(todo $todo) { $this->authorize('create',$todo); $this->validate([ 'description' => ['required','max:128'], ]); sleep(0.5); todo::create([ 'user_id' => session('user_id'), 'description' => $this->description, ]); $this->reset(); } public function render() { return view('livewire.elements.todolist.todolist',[ 'todos' => todo::orderBy('is_done','ASC')->orderBy('created_at','DESC')->get(), ]); } }
TodoPolicy代码
namespace App\Policies; use App\Models\User; use App\Models\todo; use Illuminate\Auth\Access\Response; class todoPolicy { /** * Determine whether the user can view any models. */ public function viewAny(User $user): bool { } /** * Determine whether the user can view the model. */ public function view(User $user, todo $todo): bool { } /** * Determine whether the user can create models. */ public function create(User $user): bool { return true; } /** * Determine whether the user can update the model. */ public function update(User $user, todo $todo): bool { // } /** * Determine whether the user can delete the model. */ public function delete(User $user, todo $todo): bool { // } /** * Determine whether the user can restore the model. */ public function restore(User $user, todo $todo): bool { // } /** * Determine whether the user can permanently delete the model. */ public function forceDelete(User $user, todo $todo): bool { // } }
修复方案
1. 修正类名大小写(核心问题)
Laravel的自动注册机制依赖严格的大驼峰命名规则:
- 将模型文件重命名为
Todo.php,类名改为Todo:
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Todo extends Model { // 保持原有字段、关联等配置不变 }
- 将Policy文件重命名为
TodoPolicy.php,类名改为TodoPolicy,同时更新模型引用:
namespace App\Policies; use App\Models\User; use App\Models\Todo; // 修正为大驼峰的Todo use Illuminate\Auth\Access\Response; class TodoPolicy // 修正为大驼峰类名 { // 其余方法保持不变 }
2. 修正create权限的调用方式
create权限不需要传入模型实例(创建时还未生成对象),应传入模型类,同时移除add方法中不必要的模型参数:
修改Livewire组件的add方法:
public function add() { // 移除todo $todo参数 $this->authorize('create', Todo::class); // 传入模型类而非实例 $this->validate([ 'description' => ['required','max:128'], ]); sleep(0.5); Todo::create([ // 模型类改为Todo 'user_id' => session('user_id'), 'description' => $this->description, ]); $this->reset(); }
3. 处理未认证用户场景(可选)
如果需要允许未登录用户创建Todo,需修改Policy的create方法,允许用户为null:
public function create(?User $user): bool // ?User 表示用户可以未认证 { return true; }
4. 手动注册Policy(兜底方案)
若自动注册仍失效,在App\Providers\AuthServiceProvider的$policies数组中手动绑定:
namespace App\Providers; use App\Models\Todo; use App\Policies\TodoPolicy; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; class AuthServiceProvider extends ServiceProvider { protected $policies = [ Todo::class => TodoPolicy::class, ]; // 其余代码保持不变 }
内容的提问来源于stack exchange,提问作者Mehdi
相关产品推荐
相关产品推荐

