在Laravel中授权之前检查FormRequest的验证规则

时间:2019-03-11 14:37:51

标签: php laravel json-api

我正在使用JSON:API规范在Laravel中实现API。

其中有一个资源,我们称它为Ponds,与另一个资源具有多对多的关系,我们称它为Ducks。

根据JSON:API规范,为了删除这种关系,我应使用DELETE / ponds / {id} / relationships / ducks 端点,并要求以下正文:

{
    "data": [
        { "type": "ducks", "id": "123" },
        { "type": "ducks", "id": "987" }
    ]
}

这由PondRemoveDucksRequest处理,如下所示:

<?php
...
class PondRemoveDucksRequest extends FormRequest
{
    public function authorize() 
    {
        return $this->allDucksAreRemovableByUser();
    }

    public function rules()
    {
        return [
            "data.*.type" => "required|in:ducks",
            "data.*.id" => "required|string|min:1"
        ];
    }

    protected function allDucksAreRemovableByUser(): bool
    {
        // Here goes the somewhat complex logic determining if the user is authorized 
        // to remove each and every relationship passed in the data array.
    }
}

问题在于,如果我发送诸如以下内容:

{
    "data": [
        { "type": "ducks", "id": "123" },
        { "type": "ducks" }
    ]
}

,我得到500,因为授权检查首先触发,并且它依赖于数组每个项目中的ID。理想情况下,我希望通过规则验证从标准消息中获取422错误。

我看到的快速解决方案是在allDucksAreRemovableByUser()方法中添加ID存在检查,但这似乎有些hacker。

是否有更好的方法先检查验证规则,然后再进行授权部分?

谢谢!

3 个答案:

答案 0 :(得分:2)

1-在App \ Requests目录中创建名为“ FormRequest”的抽象类,并覆盖 validateResolved()方法:


<?php

namespace App\Http\Requests;

use Illuminate\Validation\ValidationException;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Foundation\Http\FormRequest as BaseFormRequest;

abstract class FormRequest extends BaseFormRequest
{

    /**
     * Validate the class instance.
     *
     * @return void
     * @throws AuthorizationException
     * @throws ValidationException
     */
    public function validateResolved()
    {

        $validator = $this->getValidatorInstance();

        if ($validator->fails())
        {
            $this->failedValidation($validator);
        }

        if (!$this->passesAuthorization())
        {
            $this->failedAuthorization();
        }
    }

}

2-使用自定义FormRequest扩展您的FormRequests

<?php

namespace App\Http\Requests\Orders;

use App\Http\Requests\FormRequest;

class StoreOrderRequest extends FormRequest
{



}


答案 1 :(得分:0)

这里的方法与您尝试的方法略有不同,但是它可以为您实现所需的结果。

如果您要尝试验证给定的鸭子ID是否属于用户,可以在规则本身中完成以下操作:

"data.*.id" => "exists:ducks,id,user_id,".Auth::user()->id

此规则询问在ducks表中是否存在与id匹配的记录,以及user_id是当前登录的user_id的位置。

如果使用'bail'将其链接到现有规则(必需| string | min:1),则除非先通过了其他三个规则,否则它将不会运行查询:

"data.*.id" => "bail|required|string|min:1|exists:ducks,id,user_id,".Auth::user()->id

答案 2 :(得分:-1)

$this->getValidatorInstance()->validate();方法开始时添加authorize()