You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 09:27:06