如果授权失败,我正在尝试重定向请求。我有以下代码:
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 版本修复它?
看起来不可能
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 秒
如果您正在重新访问此线程,因为在 2021 年您希望在授权失败后重定向,您可以执行以下操作:
您不能从 failedAuthorization() 方法重定向,因为它会抛出异常(检查您扩展的基 FormRequest 类中的方法),更改返回类型的副作用是 $request 命中控制器而不是在 FormRequest 授权级别处理。
您不需要创建自定义异常类,也不需要像编辑 app/Exceptions/Handler.php 的 render() 那样干预 Laravel 核心文件,它将拾取您抛出的异常并默认渲染乏味的 403页。
您需要做的就是抛出新的 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()
你可以通过我认为的中间件/策略来完成。我不知道你是否可以从验证中做到这一点。
您可以像下面这样覆盖 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
是一个 renderable exception,即它在创建时接受响应并且应用程序将处理所述响应 - 在这种情况下重定向浏览器。
authorize()
表单请求方法只是抛出它有意义的地方之一,但您几乎可以在任何地方进行。