我注意到,如果您在使用 Laravel 异常的策略中 throw AuthorizationException($message),它会将您跳出策略,但会继续在控制器中执行,并且不会前进到 Handler::render。我假设这是他们以某种方式处理异常,但我找不到他们在哪里做这件事......所以如果有人找到发生这种情况的地方,我仍然想知道。
如果您创建自己的 AuthorizationException 并抛出它,它将按预期停止执行,并放入 Handler::render 所以我最终将此方法添加到我的策略中:
use App\Exceptions\AuthorizationException;
// ... removed for brevity
private function throwExceptionIfNotPermitted(bool $hasPermission = false, bool $allowExceptions = false, $exceptionMessage = null): bool
{
// Only throw when a message is provided, or use the default
// behaviour provided by policies
if (!$hasPermission && $allowExceptions && !is_null($exceptionMessage)) {
throw new \App\Exceptions\AuthorizationException($exceptionMessage);
}
return $hasPermission;
}
仅在 \App\Exceptions 中抛出策略的新例外:
namespace App\Exceptions;
use Exception;
/**
* The AuthorizationException class is used by policies where authorization has
* failed, and a message is required to indicate the type of failure.
* ---
* NOTE: For consistency and clarity with the framework the exception was named
* for the similarly named exception provided by Laravel that does not stop
* execution when thrown in a policy due to internal handling of the
* exception.
*/
class AuthorizationException extends Exception
{
private $statusCode = 403;
public function __construct($message = null, \Exception $previous = null, $code = 0)
{
parent::__construct($message, $code, $previous);
}
public function getStatusCode()
{
return $this->statusCode;
}
}
处理异常并在 Handler::render() 的 JSON 响应中提供消息:
public function render($request, Exception $exception)
{
if ($exception instanceof AuthorizationException && $request->expectsJson()) {
return response()->json([
'message' => $exception->getMessage()
], $exception->getStatusCode());
}
return parent::render($request, $exception);
}
我也将其从登录Handler::report中删除。