Перенаправить, если авторизация запроса не удалась в Laravel 5.5
Я пытаюсь перенаправить запрос, если авторизация не удалась. У меня есть следующий код:
class ValidateRequest extends Request{
public function authorize(){
// some logic here...
return false;
}
public function rules(){ /* ... */}
public function failedAuthorization() {
return redirect('safepage');
}
}
По умолчанию я перенаправлен на страницу ошибки 403, но я хотел бы указать какой-то конкретный маршрут. Я заметил этот метод failedAuthorization()
работает, но redirect()
метод не работает...
Ранее этот код хорошо работал с Laravel 5.1, но я использовал forbiddenResponse()
способ перенаправить неправильный запрос. Как я могу это исправить с новой версией LTS?
4 ответа
Похоже, это невозможно redirect()
прямо из обычая ValidateRequest
учебный класс. Единственное решение, которое я нашел, - это создать пользовательское исключение и обработать его в классе Handler. Итак, теперь он работает со следующим кодом:
приложение / Запросы /ValidateRequest.php
class ValidateRequest extends Request{
public function authorize(){
// some logic here...
return false;
}
public function rules(){
return [];
}
public function failedAuthorization() {
$exception = new NotAuthorizedException('This action is unauthorized.', 403);
throw $exception->redirectTo("safepage");
}
}
Приложение / Исключения /NotAuthorizedException.php
<?php
namespace App\Exceptions;
use Exception;
class NotAuthorizedException extends Exception
{
protected $route;
public function redirectTo($route) {
$this->route = $route;
return $this;
}
public function route() {
return $this->route;
}
}
и приложение / Исключения /Handler.php
...
public function render($request, Exception $exception){
...
if($exception instanceof NotAuthorizedException){
return redirect($exception->route());
}
...
}
Итак, это работает, но гораздо медленнее, чем я ожидал... Простое измерение показывает, что обработка и перенаправление занимают 2,1 с, но с Laravel 5.1 то же действие (и тот же код) занимает всего 0,3 с.
Добавление NotAuthorizedException::class
к $dontReport
собственность вообще не помогает...
Обновить
Работает намного быстрее с php 7.2, занимает 0,7 с
Если вы повторно посещаете эту ветку, потому что в 2021 году вы хотите перенаправить после неудачной авторизации, вот что вы можете сделать:
Вы не можете перенаправить из метода failedAuthorization(), потому что ожидается, что он вызовет исключение (проверьте метод в базовом классе FormRequest, который вы расширяете), побочным эффектом изменения типа возврата является запрос $, попадающий в контроллер, а не обрабатываемый на уровне авторизации FormRequest.
Вам не нужно создавать собственный класс исключений, а также вмешиваться в основные файлы Laravel, например редактировать render () app / Exceptions / Handler.php, который подберет созданное вами исключение и по умолчанию отобразит мягкую страницу 403.
Все, что вам нужно сделать, это выбросить новое исключение HttpResponseException(). В справочном API Laravel мы видим, что его задача - «Создать новый экземпляр исключения ответа HTTP». и это именно то, что мы хотим, верно?
Итак, нам нужно передать этому исключению $response. Мы можем передать редирект или ответ в формате JSON!
Перенаправление:
protected function failedAuthorization()
{
throw new HttpResponseException(response()->redirectToRoute('postOverview')
->with(['error' => 'This action is not authorized!']));
}
Итак, мы создаем новый экземпляр HttpResponseException и используем помощник response () , который имеет этот очень полезный метод redirectToRoute ('routeName'), который мы можем связать с известным методом with() и передать сообщение об ошибке. для отображения во внешнем интерфейсе.
JSON: навеяны этой темой
throw new HttpResponseException(response()->json(['error' => 'Unauthorized action!'], 403));
Это оно. Вам не нужно делать ЛЮБЫЕ проверки для проверки или авторизации в вашем контроллере, все делается в фоновом режиме, прежде чем он попадет в контроллер. Вы можете проверить это, поставив dd («достигнутый контроллер»); в верхней части метода контроллера, и он не должен срабатывать. Таким образом вы сохраните свой контроллер тонким и разделите проблемы :)
Замечание: после lara 5.4 запрещенныйResponse () был заменен на failedAuthorization()
Вы можете сделать это через промежуточное ПО / политику, я думаю. Я не знаю, можете ли вы сделать это из проверки.
Вы можете переопределить функцию из FormRequest следующим образом:
/**
* Handle a failed authorization attempt.
*
* @return void
*
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
protected function failedAuthorization()
{
throw new AuthorizationException('This action is unauthorized.');
}
И перенаправить куда хочешь.
Ответ на 2023 год (Laravel v8++):
<?php
namespace App\Http\Requests;
class MyCustomFormRequest extends Request
{
public function authorize()
{
// check your logic, and:
throw new \Illuminate\Http\Exceptions\HttpResponseException(
redirect()->route('your route')->with('error', 'your error')
);
}
}
HttpResponseException
является визуализируемым исключением , т.е. оно принимает ответ при создании, и приложение будет обрабатывать этот ответ - в этом случае перенаправить браузер.
The authorize()
Метод запроса формы — это лишь одно из мест, где его использование имеет смысл, но сделать это можно практически откуда угодно.