使用Auth的Laravel Handler错误上下文出错

时间:2017-11-30 10:01:30

标签: php laravel exception php-7 laravel-5.5

经过一番调查,我发现了以下内容:

如果用户向我们的API发出错误的承载请求,则会抛出 OAuthServerException ,并且处理程序类的报告方法为调用以查找要添加到报告信息的上下文。在上下文方法期间,将调用 Auth 外观,这是双重失败并调用brut 503错误的位置。

要隐藏问题,我已将OAuthServerException :: class添加到$ dontreport属性,但这并没有解决问题,它不应该被隐藏......

是否可以帮助我找出为什么在抛出OAuthServerException时Auth facade失败?

修改:要添加一些"上下文",我发现此错误报告和P​​R关联看起来像我的问题,但没有谈论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 [];
        }
    }

1 个答案:

答案 0 :(得分:0)

就像你说的那样,在报告异常时会调用Auth::方法,这反过来会导致抛出相同类型的另一个异常。

如果您不想dontReport此异常,则可以覆盖context方法并让其返回[]

但是,报告OAuthServerException可能确实有意义。了解基本异常处理程序如何报告Illuminate\Auth\AuthenticationExceptionIlluminate\Auth\Access\AuthorizationException。这将是您未报告的另一个与身份验证相关的异常。