php - 带有 Auth 的 Laravel 处理程序错误上下文中的错误

标签 php laravel exception php-7 laravel-5.5

经过一些调查,这是我的发现:

当用户使用错误的 Bearer 向我们的 API 发出请求时,将抛出 OAuthServerException 并且 Handler 类的 report 方法要求寻找上下文以添加到报告信息中。在 context 方法期间,调用了 Auth facade,这是它双重失败并调用 brut 503 错误的地方。

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

你能帮我弄清楚为什么在抛出 OAuthServerException 时 Auth facade 会失败吗?

编辑:为了添加一些“上下文”,我发现这个错误报告和相关的 PR 看起来像我的问题,但没有谈论 Auth facade ... 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 [];
        }
    }

最佳答案

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

如果您不想dontReport这个异常,您可以改写context方法并让它只返回[]

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

关于php - 带有 Auth 的 Laravel 处理程序错误上下文中的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47570630/

相关文章:

php - Ajax/php header :Location

php - 不能在同一个 Twig 文件中使用循环 2 次

laravel - Webpack 监视脚本在几次成功编译后抛出错误。Laravel Homestead

php - 在 Laravel 中从数据库中独特地选择列

java - 抛出异常并从 finally 返回 - Tomcat 挂起

php - 更快地找到数组中单词之间的最小距离

php - 查看表 IF CASE 条件不能正常工作

拉拉维尔 5.8 : A facade root has not been set after homestead restart

haskell - 如何使用异常处理在 Haskell 中编写 "retryForever"函数?

java - 当用户 session 过期或返回 null 时抛出异常