Laravel 策略总是 returns 403 未经授权

Laravel Policy Always returns 403 unauthorized

我正在制作一个使用 jwt 作为身份验证系统的应用程序,

当我尝试更新我的 Category 模型时,政策总是 returns 403 未授权,

我正在使用 apiResourcecrud 我的模型。

我的代码

api.php中:

Route::apiResource('category', CategoryController::class);

CategoryController.php中:

    public function update(Request $request, $id)
    {
        // print_r($request->all());
        $validator = Validator::make(
            $request->all(),
            [
                'name' => 'required|min:2|unique:categories,name,' . $request->id,
                'description' => 'required|min:1',
            ],
            [
                "name.unique" => "اسم الصنف مستخدم مسبقا",
                "name.required" => "اسم الصنف مطلوب",
                "name.min" => "اسم الصنف يجب أن يحتوي على حرفين على الأقل",

                "description.required" => "وصف الصنف مطلوب",
            ]
        );
        if ($validator->fails()) {
            return response()->json(['errors' => $validator->messages(), 'status' => 422], 200);
        }
        $category = Category::find($id);
        $category->name = $request->name;
        $category->description = $request->description;
        $category->save();
        return response()->json([
            "message" => "تم تحديث الصنف",
            "status" => 200
        ], 200);
    }

CategoryPolicy.php中:

    public function update(User $user, Category $category)
    {

        return $category->user_id === $user->id;
    }

似乎 request 甚至没有达到 CategoryPolicy.php 中的 update 方法 因为即使该方法总是返回 true 它也不起作用 :

    public function update(User $user, Category $category)
    {

        return true;
    } 

无论如何,viewAny 方法都按预期工作。

I'm using axios to fetch and update data and I'm sending the request with the bearer token and every thing is working ok except the issue above.

CategoryController.php中,而不是注入$id:

public function update(Request $request, $id)

尝试注入类型提示模型实例:

public function update(Request $request, Category $category)

并删除 find() 命令:

//$category = Category::find($id);

生成新控制器时,您还可以使用此 artisan 命令在函数参数中包含类型提示模型。

php artisan make:controller CategoryController --api --model=Category

很难看出哪里出了问题,因为它也可能是中间件和 JWT 令牌。您可以做的是在更新方法中检查用户是否已登录,将以下内容添加为方法中的第一行。如果为 false,请检查您的 JWT 实现

dd(auth()->check());

我还建议清理您的控制器:

class CategoryController
{
    /**
     * CateogryController constructor.
     */
    public function __construct()
    {
        $this->authorizeResource(Category::class); // if your are using CRUD, validate like this
    }

    /**
     * Update specific resource.
     *
     * @param Category $category
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function update(Category $category, CategoryRequest $request): JsonResponse
    {

// notice the model route binding. 
        $this->authorize('update', $category); // If you only have update method, but remove the __construct.

        $category->update([
            'name' => $request->get('name'),
            'description' => $request->get('description')
        ]);

        return response()->json(['message' => 'تم تحديث الصنف']); // take the 200 from the headers, not add it in as text. 
    }

}

您的请求与此类似:

class CategoryRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true; // you could consider to validate the user->category relation. I like it more separated and put it in a separated policy.
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name' => 'required|min:2|unique:categories,name',
            'description' => 'required|min:1',
        ];
    }

    /**
     * @return string[]
     */
    public function messages()
    {
        return [
            "name.unique" => "اسم الصنف مستخدم مسبقا",
            "name.required" => "اسم الصنف مطلوب",
            "name.min" => "اسم الصنف يجب أن يحتوي على حرفين على الأقل",
            "description.required" => "وصف الصنف مطلوب",
        ];
    }
}

你的政策是这样的:

class CategoryPolicy
{
    use HandlesAuthorization;

    /**
     * Determine if the user can update category resource.
     *
     * @param User $user
     * @param Category $category
     * @return bool
     */
    public function update(User $user, Category $category): bool
    {
        return $user->categories()->where('id', $category->id)->exists(); // or somthing like this.
    }
}