使用 Laravel 和 Passport 在身份验证失败时响应状态码 401?

Posted

技术标签:

【中文标题】使用 Laravel 和 Passport 在身份验证失败时响应状态码 401?【英文标题】:Respond with status code 401 on authentication failure using Laravel and Passport? 【发布时间】:2017-07-28 04:27:06 【问题描述】:

我正在配置一个 Laravel 项目以使用 Passport 令牌身份验证。一切似乎都在工作,但是当auth:api 中间件失败时,它会以200 的状态和响应正文中的一堆html 响应客户端。相反,我希望它以401 的状态响应。

我在 Laravel Passport 源代码或文档中找不到有关执行此类操作的任何内容。我什至找不到中间件的来源。

我的测试路线:

Route::get('/protected', function () 
    return response()->json([
        'success' => true
    ]);
)->middleware('auth:api');

配置/auth.php

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'passport',
        'provider' => 'appUsers',
    ],
],

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\Models\User::class,
    ],

    'appUsers' => [
        'driver' => 'eloquent',
        'model' => App\Models\AppUser::class
    ],
],

【问题讨论】:

【参考方案1】:

在中间件中你可以这样返回:

return abort(401);

【讨论】:

我没有写中间件。我正在尝试使用 Larave/Passport 提供的中间件(auth:api)。 不想改源码的可以扩展中间件。 auth 中间件仅包含 1 个方法。难道我不必只覆盖该方法并完全重写它吗? 您的新中间件应该扩展 Illuminate\Auth\Middleware\Authenticate。【参考方案2】:

如果用户没有进行身份验证,Laravel 会抛出一个AuthenticationException

此异常由Illuminate/Foundation/Exceptions/Handler.php 中的render 方法处理,并依次调用您的app/Exceptions/Handler.php 中定义的unauthenticated() 方法:

protected function unauthenticated($request, AuthenticationException $exception)

    if ($request->expectsJson()) 
        return response()->json(['error' => 'Unauthenticated.'], 401);
    

    return redirect()->guest(route('login'));

如您所见,默认情况下,如果请求需要 JSON 响应,您将收到带有 JSON 错误正文的 401。如果请求不期望 JSON,则将请求重定向到登录页面。

如果您的请求具有Accept: application/json 标头或X-Requested-With: XMLHttpRequest,则expectsJson() 方法将返回true。 Accept: application/json 标头更适合 api 调用,而 X-Requested-With: XMLHttpRequest 标头用于 ajax 调用。

因此,无需更改任何应用程序代码,只需确保请求包含 Accept: application/json 标头即可。

但是,如果您需要在用户未通过身份验证时执行不同的操作,您可以在app/Exceptions/Handler.php 中修改此unauthenticated() 方法:

protected function unauthenticated($request, AuthenticationException $exception)

    if ($request->expectsJson()) 
        return response()->json(['error' => 'Unauthenticated.'], 401);
    

    // return a plain 401 response even when not a json call
    return response('Unauthenticated.', 401);

【讨论】:

上帝保佑你兄弟 如果您正在使用Laravel 5.5 并且这些都不起作用,并且如果您记得删除所有类型的缓存,请尝试在您的所有服务器中运行php artisan config:cache。一起被困​​了几个小时,只有这样才能使它起作用。希望它可以帮助别人!【参考方案3】:

您可以通过在请求中发送此标头来解决它。

Accept : application/json

这将发送带有401 状态码的消息。


    "message": "Unauthenticated."

【讨论】:

我想向这个 JSON 响应添加自定义代码,例如 ( "error" : 401 "message": "Unauthenticated." )。我该怎么做? 我不明白这个答案,您能否补充一下,告诉我们如何发送该标头? @Gjaa 您可以查看此答案以了解如何在 Laravel 响应中添加标头 ***.com/questions/17548569/… 如果您正在使用Laravel 5.5 并且这些都不起作用,并且如果您记得删除所有类型的缓存,请尝试在您的所有服务器中运行php artisan config:cache。一起坚持了几个小时,只有这样才能使它起作用。希望它可以帮助别人!

以上是关于使用 Laravel 和 Passport 在身份验证失败时响应状态码 401?的主要内容,如果未能解决你的问题,请参考以下文章

使用 VueX 和 Laravel Passport 进行身份验证

Laravel 5.3 + Passport:总是未经身份验证的错误

Laravel Passport API:检索经过身份验证的令牌

Laravel Passport 没有身份验证

获取经过身份验证的用户 Laravel/Lumen Passport

使用 Laravel Lumen + Passport 获取经过身份验证的用户时出现问题