【发布时间】:2018-05-14 05:10:21
【问题描述】:
经过一番调查,我发现了以下内容:
当用户使用错误的 Bearer 向我们的 API 发出请求时,会抛出 OAuthServerException 并且 Handler 类的 report 方法是调用以查找要添加到报告信息的上下文。在 context 方法期间,调用了 Auth 外观,这是它双重失败的地方,并调用了粗暴的 503 错误。
为了隐藏问题,我在 $dontreport 属性中添加了 OAuthServerException::class,但这并不能解决问题,它不应该被隐藏...
您能否帮我弄清楚为什么在抛出 OAuthServerException 时 Auth 门面会失败?
编辑:为了添加一些“上下文”,我发现这个错误报告和相关的 PR 看起来像我的问题,但没有谈论 Auth 门面...... https://github.com/laravel/framework/issues/21041 但也许它是链接的。
Edit2:用户按预期扩展了 Laravel 的 Auth\User:
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Auth;
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable
{
use ModelTrait, HasApiTokens, Notifiable;
/* some methods */
}
Edit3:添加 Handler 类
namespace App\Exceptions;
use Exception;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Foundation\Testing\HttpException;
use League\OAuth2\Server\Exception\OAuthServerException;
use Symfony\Component\HttpFoundation\Response;
class Handler extends ExceptionHandler
{
/**
* A list of the exception types that should not be reported.
*
* @var array
*/
protected $dontReport = [
\Illuminate\Auth\AuthenticationException::class,
\Illuminate\Auth\Access\AuthorizationException::class,
\Symfony\Component\HttpKernel\Exception\HttpException::class,
\Illuminate\Database\Eloquent\ModelNotFoundException::class,
\Illuminate\Session\TokenMismatchException::class,
\Illuminate\Validation\ValidationException::class,
OAuthServerException::class // This is just a temporary fix
];
/**
* Report or log an exception.
*
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
*
* @param \Exception $exception
* @return void
*/
public function report(Exception $exception)
{
parent::report($exception);
}
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $exception
* @return \Illuminate\Http\Response|Response
*/
public function render($request, Exception $exception)
{
if ($exception instanceof HttpException) {
return response()->json(
['error' => $exception->getMessage()],
$exception->getCode()
);
}
if ($request->wantsJson()) {
$response = [
'errors' => 'Sorry, something went wrong.'
];
$response['message'] = $exception->getMessage();
if (get_class($exception) == 'Illuminate\Validation\ValidationException') {
$response['rules'] = $exception->validator->errors();
}
if (config('app.debug')) {
// Add the exception class name, message and stack trace to response
$response['exception'] = get_class($exception); // Reflection might be better here
$response['trace'] = $exception->getTrace();
}
// Default response of 400
$status = 400;
// If this exception is an instance of HttpException
if ($this->isHttpException($exception)) {
// Grab the HTTP status code from the Exception
$status = $exception->getStatusCode();
}
// Return a JSON response with the response array and status code
return response()->json($response, $status);
}
return parent::render($request, $exception);
}
/**
* Convert an authentication exception into an unauthenticated response.
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Auth\AuthenticationException $exception
* @return \Illuminate\Http\Response
*/
protected function unauthenticated($request, AuthenticationException $exception)
{
if ($request->expectsJson()) {
return response()->json(['error' => 'Unauthenticated.'], 401);
}
return redirect()->guest(route('login'));
}
}
这两个函数来自 Laravel\Illuminate\Foundation\Exceptions\Handler(我的 Handler 类的父类),调用 Auth 时,503 发生在上下文方法中。
/**
* Report or log an exception.
*
* @param \Exception $e
* @return mixed
*
* @throws \Exception
*/
public function report(Exception $e)
{
if ($this->shouldntReport($e)) {
return;
}
if (method_exists($e, 'report')) {
return $e->report();
}
try {
$logger = $this->container->make(LoggerInterface::class);
} catch (Exception $ex) {
throw $e; // throw the original exception
}
$logger->error(
$e->getMessage(),
array_merge($this->context(), ['exception' => $e]
));
}
/**
* Get the default context variables for logging.
*
* @return array
*/
protected function context()
{
try {
return array_filter([
'userId' => Auth::id(),
'email' => Auth::user() ? Auth::user()->email : null,
]);
} catch (Throwable $e) {
return [];
}
}
【问题讨论】:
-
您可能需要添加一些 sn-ps 代码来帮助查看到底发生了什么。我假设您正在使用它的 Passport。你的中间件是什么样的?任何其他与规范不同的配置?
-
@Paul Handler 类是 Laravel 中直接开箱即用的类,对于 Passport 也是一样...
-
我们需要 sn-ps 来帮助你@Paul
-
@PaulSantos 我已经添加了处理程序类,但我真的不知道要提供什么代码 sn-p。中间件,它也是来自 Laravel Passport 的,没什么新鲜的。
-
@Roadirsh,您是否更新了 config/auth.php 以使用模型的正确命名空间?
标签: php laravel exception php-7 laravel-5.5