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

Redirect if request authorization is failed in 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 版本修复它?

我认为你可以通过 middleware/policy 来完成。我不知道你是否可以从验证中做到这一点。

您可以像下面这样重写 FormRequest 中的函数:

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

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

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

更新: 方法 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 s

NotAuthorizedException::class 添加到 $dontReport 属性 根本没有帮助...

更新

php 7.2 运行速度更快,需要 0.7 秒

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

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

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

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

因此我们需要将此异常传递给 $response。我们可以传递重定向或 JSON 响应!

重定向:

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

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

JSON: 受此启发 topic

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

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

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