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."
我当时以为是我的哪里操作不对,直到我将课程源码下下来之后,测试一下发现确实不是我的操作问题
错误重现
- 当 jwt token 为正确的时候,发现我们是可以正常获取到用户信息的。如下图所示
![laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401,而会报错 "message": "Unauthenticated." 或者 Route [login] not defined. 问题分析及解决方案](https://cdn.learnku.com/uploads/images/202002/07/23849/Mme2hMfT9I.png!large)
- 故意将 jwt token 改成错误的,就会报错,但是并非报 401 错误
![laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401,而会报错 "message": "Unauthenticated." 或者 Route [login] not defined. 问题分析及解决方案](https://cdn.learnku.com/uploads/images/202002/07/23849/fJYahxwLQN.png!large)
- 如果你项目中没有路由名称为 login 的路由时,会报错
![laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401,而会报错 "message": "Unauthenticated." 或者 Route [login] not defined. 问题分析及解决方案](https://cdn.learnku.com/uploads/images/202002/07/23849/yND0D8WKkw.png!large)
报错分析
- 我们是通过
auth:api中间件来判断用户是否已经登录的,那么此时我们定位到App\Http\Kernel.php文件中
![laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401,而会报错 "message": "Unauthenticated." 或者 Route [login] not defined. 问题分析及解决方案](https://cdn.learnku.com/uploads/images/202002/07/23849/zewuwYp2WA.png!large)
- 然后我们继续定位到
App\Http\Middleware\Authenticate.php文件中
![laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401,而会报错 "message": "Unauthenticated." 或者 Route [login] not defined. 问题分析及解决方案](https://cdn.learnku.com/uploads/images/202002/07/23849/RqR4ElEJtW.png!large)
我们可以看到 \App\Http\Middleware\Authenticate::class@redirectTo 方法,当不是 ajax 请求的时候,就跳转到了 login 路由,那么 "message": "Unauthenticated." 又是如何产生的 呢?
- 我们发现
\App\Http\Middleware\Authenticate类 继承了Illuminate\Auth\Middleware\Authenticate类,那么我们继续定位到Illuminate\Auth\Middleware\Authenticate中
![laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401,而会报错 "message": "Unauthenticated." 或者 Route [login] not defined. 问题分析及解决方案](https://cdn.learnku.com/uploads/images/202002/07/23849/eni9YFhsML.png!large)
- 因为是中间件,因此我们直接看
Illuminate\Auth\Middleware\Authenticate::class@handle方法
![laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401,而会报错 "message": "Unauthenticated." 或者 Route [login] not defined. 问题分析及解决方案](https://cdn.learnku.com/uploads/images/202002/07/23849/4ZbpiOoqJ9.png!large)
继而我们可以看到如果登录验证失败的话就直接抛出 AuthenticationException 异常了
![laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401,而会报错 "message": "Unauthenticated." 或者 Route [login] not defined. 问题分析及解决方案](https://cdn.learnku.com/uploads/images/202002/07/23849/zJlvPQPoXB.png!large)
解决方案
重新自定义一个路由中间件,自己实现登录验证
- 执行以下
artisan命令,生成CheckUserLogin中间件文件
php artisan make:middleware CheckUserLogin
- 在
App\Http\Middleware\CheckUserLogin::class@handle方法中写登录验证逻辑
![laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401,而会报错 "message": "Unauthenticated." 或者 Route [login] not defined. 问题分析及解决方案](https://cdn.learnku.com/uploads/images/202002/07/23849/oTQ42V0FS4.png!large)
- 在
App\Http\Kernel中注册路由中间件
![laravel 6.x 版本中,如果 JWT 不正确的时不会抛出 401,而会报错 "message": "Unauthenticated." 或者 Route [login] not defined. 问题分析及解决方案](https://cdn.learnku.com/uploads/images/202002/07/23849/UsGWENdIkx.png!large)
- 使用刚刚自定义的验证登录路由,在路由文件中
// 登录后可以访问的接口
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 的指点。👍

关于 LearnKu
推荐文章: