Laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401

L03 Laravel 教程 - 实战构架 API 服务器 ( Laravel 6.x ) 一书中 5.1. 获取用户信息,如果 jwt token 失效,报错 Route [login] not defined. 问题分析

报错情况

  • 如果当前项目中没有定义 login 路由时( 不管是 web.php 或者 api.php 中都没有定义 login 路由)会报错
Route [login] not defined.
  • 如果当前项目中有定义 login 路由时,jwt token 失效的话会报错
"message": "Unauthenticated."

我当时以为是我的哪里操作不对,直到我将课程源码下下来之后,测试一下发现确实不是我的操作问题

错误重现

  1. 当 jwt token 为正确的时候,发现我们是可以正常获取到用户信息的。如下图所示

laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401,而会报错 "message": "Unauthenticated." 或者 Route [login] not defined. 问题分析及解决方案

  1. 故意将 jwt token 改成错误的,就会报错,但是并非报 401 错误

laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401,而会报错 "message": "Unauthenticated." 或者 Route [login] not defined. 问题分析及解决方案

  1. 如果你项目中没有路由名称为 login 的路由时,会报错

laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401,而会报错 "message": "Unauthenticated." 或者 Route [login] not defined. 问题分析及解决方案

报错分析

  1. 我们是通过 auth:api 中间件来判断用户是否已经登录的,那么此时我们定位到 App\Http\Kernel.php 文件中

laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401,而会报错 "message": "Unauthenticated." 或者 Route [login] not defined. 问题分析及解决方案

  1. 然后我们继续定位到 App\Http\Middleware\Authenticate.php 文件中

laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401,而会报错 "message": "Unauthenticated." 或者 Route [login] not defined. 问题分析及解决方案

我们可以看到 \App\Http\Middleware\Authenticate::class@redirectTo 方法,当不是 ajax 请求的时候,就跳转到了 login 路由,那么 "message": "Unauthenticated." 又是如何产生的 呢?

  1. 我们发现 \App\Http\Middleware\Authenticate 类 继承了 Illuminate\Auth\Middleware\Authenticate 类,那么我们继续定位到 Illuminate\Auth\Middleware\Authenticate

laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401,而会报错 "message": "Unauthenticated." 或者 Route [login] not defined. 问题分析及解决方案

  1. 因为是中间件,因此我们直接看 Illuminate\Auth\Middleware\Authenticate::class@handle 方法

laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401,而会报错 "message": "Unauthenticated." 或者 Route [login] not defined. 问题分析及解决方案

继而我们可以看到如果登录验证失败的话就直接抛出 AuthenticationException 异常了

laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401,而会报错 "message": "Unauthenticated." 或者 Route [login] not defined. 问题分析及解决方案

解决方案

重新自定义一个路由中间件,自己实现登录验证

  1. 执行以下 artisan 命令,生成 CheckUserLogin 中间件文件
php artisan make:middleware CheckUserLogin
  1. App\Http\Middleware\CheckUserLogin::class@handle 方法中写登录验证逻辑

laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401,而会报错 "message": "Unauthenticated." 或者 Route [login] not defined. 问题分析及解决方案

  1. App\Http\Kernel 中注册路由中间件

laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401,而会报错 "message": "Unauthenticated." 或者 Route [login] not defined. 问题分析及解决方案

  1. 使用刚刚自定义的验证登录路由,在路由文件中
        // 登录后可以访问的接口
        Route::middleware(['checkUserLogin'])->group(function() {

            // 当前登录用户信息
            Route::get('user', 'Auth\UsersController@me')->name('user.show');

            Route::get('tests', 'Api\ApiTestsController@index')->name('tests.index');

        });

以上是我目前的解决方案,如果你有其它的解决方案,或者以上我理解有问题,还望指正!

20200209 更新

我的业务场景是想授权验证失败,框架就能够直接给我返回一段以下这样的数据

{
    "code": 401,
    "msg": "登录已过期,请重新登录"
)   

但是框架是直接返回了

{"message": "Unauthenticated."}

不符合我自己的数据格式要求,因此需要在 app\Exceptions\Handler.php 文件中做一下处理。非常感谢课程作者 liyu001989 的指点。👍

《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
liyu001989
最佳答案

file

重现不了,你先确定一下 header 到底对不对。真的需要手动处理,也是在 app/Exceptions/Handler.php 里面处理

4年前 评论
讨论数量: 6
liyu001989

file

重现不了,你先确定一下 header 到底对不对。真的需要手动处理,也是在 app/Exceptions/Handler.php 里面处理

4年前 评论

我也遇到了相同的问题 Route [login] not defined.
修改 app\Http\Middleware\Authenticate.php 后 直接显示了 401页面而不是
{
“code”: 401,
“msg”: “登录已过期,请重新登录”
)
最终因为懒惰在 routes\api.php 里面添加了个 login 直接返回 [“code” => 401,”msg” => “登录已过期,请重新登录”]

3年前 评论
Alcohol 2年前
1443980457 1年前
magicMark 1年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!