#laravel #validation #authorization #laravel-validation #laravel-formrequest
Вопрос:
Я использую пользовательские классы запросов, которые расширяют Laravavel FormRequest
(Руководство пользователя, документация API), чтобы
- для проверки входных параметров и
- для авторизации запроса.
Скелет выглядит так:
class MyRequest extends FormRequest {
/**
* Determines if the user is authorized to make this request.
*/
public function authorize(): bool {
// TODO: Put your authorization logic here
}
/**
* Returns the validation rules that apply to the request.
*/
public function rules(): array
{
// TODO: Define your validation rules here
}
}
Обычно и конкретно в моем случае решение о том, имеет ли пользователь право делать запрос, зависит от входных параметров. Следовательно, я ожидал, что синтаксис входных параметров сначала проверяется, а затем запрос авторизуется. В частности, для правильной авторизации очень часто необходимо запускать запросы к БД, используя входные параметры запроса. Очевидно, что запрос к БД следует выполнять только в том случае, если синтаксис входных параметров уже проверен.
Сказав это, я ожидал бы следующего порядка событий
- аутентификация пользователя (происходит в промежуточном программном обеспечении, здесь выходит за рамки)
- проверка входных параметров (например, вызывается метод
rules
) - авторизация пользователя (например, вызывается метод
authorize
)
Однако Laravel вызывает 2. и 3. в обратном порядке. Следовательно, пользователь должен быть авторизован в тот момент, когда ввод еще не был подтвержден. Похоже, что проблемный код находится внутри IlluminateValidationValidatesWhenResolvedTrait::validateResolved
. Этот метод сначала вызывает логику авторизации, а затем требует проверки входных данных.
Предложенное решение
На данный момент я подумываю о том, чтобы написать свой собственный базовый класс FormRequestWithBugfix
, расширить его от FormRequest
перезаписи validateResolved
таким образом, чтобы он вызывал методы, которые он лучше упорядочивает, а затем использовал FormRequestWithBugfix
в качестве общего базового класса во всем моем проекте.
Questions:
- Будет ли предлагаемое решение работать? Есть ли какие-либо угловые случаи, о которых я должен знать, которые не рассматриваются предлагаемым решением?
- Каковы причины, по которым Laravel реализовал это таким образом на первом этапе? Я предполагаю, что должны быть веские причины сделать это так, как это сделал Ларавель.
- Есть ли какие-либо последствия для безопасности, о которых я должен знать? Каковы потенциальные недостатки в случае изменения заказа?