如果在 Laravel 中请求授权失败则重定向

问题描述 投票:0回答:4

如果授权失败,我正在尝试重定向请求。我有以下代码:

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 版本修复它?

laravel-5 redirect unauthorized
4个回答
3
投票

看起来不可能

redirect()
直接从自定义
ValidateRequest
类。我找到的唯一解决方案是创建自定义异常,然后在 Handler 类中处理它。所以,现在它适用于以下代码:

更新: 方法

redirectTo()
已更新,使解决方案适用于 Laravel 6.x 及更高版本

app/Requests/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");
    }
}

app/Exceptions/NotAuthorizedException.php

<?php

namespace App\Exceptions;

use Exception;

class NotAuthorizedException extends Exception
{
    protected $route;

    public function redirectTo($route) {
        $this->route = $route;
    
        abort(Redirect::to($route));
    }
    
    public function route() {
        return $this->route;
    }
}

app/Exceptions/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 秒


1
投票

如果您正在重新访问此线程,因为在 2021 年您希望在授权失败后重定向,您可以执行以下操作:

  1. 您不能从 failedAuthorization() 方法重定向,因为它会抛出异常(检查您扩展的基 FormRequest 类中的方法),更改返回类型的副作用是 $request 命中控制器而不是在 FormRequest 授权级别处理。

  2. 您不需要创建自定义异常类,也不需要像编辑 app/Exceptions/Handler.php 的 render() 那样干预 Laravel 核心文件,它将拾取您抛出的异常并默认渲染乏味的 403页。

  3. 您需要做的就是抛出新的 HttpResponseException() 在 Laravel 参考 API 中我们可以看到它的工作是“创建一个新的 HTTP 响应异常实例”。这正是我们想要的,对吧?

所以我们需要给这个Exception传递一个$response。我们可以传递重定向或 JSON 响应!

重定向:

protected function failedAuthorization()
{
    throw new HttpResponseException(response()->redirectToRoute('postOverview')
        ->with(['error' => 'This action is not authorized!']));
}

所以我们正在创建 HttpResponseException 的一个新实例,我们使用 response() 助手,它有这个超级有用的 redirectToRoute('routeName') 方法,我们可以进一步链接众所周知的 with() 方法并传递在前端显示的错误消息。

JSON: 受此topic

启发
throw new HttpResponseException(response()->json(['error' => 'Unauthorized action!'], 403));

就是这样。 您不必在控制器中进行任何验证或授权检查,一切都在到达控制器之前在后台完成。您可以通过放置一个 dd('reached controller'); 来测试它在你的控制器方法的顶部,它不应该被触发。 这样你就可以让你的控制器保持精简和独立的关注点:)

旁注: forbiddenResponse() 在 lara 5.4 之后被替换为 failedAuthorization()


0
投票

你可以通过我认为的中间件/策略来完成。我不知道你是否可以从验证中做到这一点。

您可以像下面这样覆盖 FormRequest 中的函数:

   /**
     * Handle a failed authorization attempt.
     *
     * @return void
     *
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    protected function failedAuthorization()
    {
        throw new AuthorizationException('This action is unauthorized.');
    }

然后重定向到你想要的地方。


0
投票

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
是一个 renderable exception,即它在创建时接受响应并且应用程序将处理所述响应 - 在这种情况下重定向浏览器。

authorize()
表单请求方法只是抛出它有意义的地方之一,但您几乎可以在任何地方进行。

© www.soinside.com 2019 - 2024. All rights reserved.