[jwt 做多用户表验证] jwt.auth 中间件一直报错找不到用户
环境
机器: CentOS release 6.10 (Final)
语言: PHP 7.2.24
框架: laravel 5.4
插件: tymon/jwt-auth 1.0
情景
一个 web 项目使用 tymon/jwt-auth 1.0
做 API 用户验证,用户表为自定义的 customer
表(user
表被用作后台用户表来用),用户登录可以正常使用,但是在登录后调用需检验登录状态的接口时会报错: UnauthorizedHttpException
: “User not found”
(使用 jwt.auth
中间件)。
代码
// config/auth.php
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
// 'driver' => 'token',
'driver' => 'jwt',
'provider' => 'customers',
],
],
// 控制器中间件声明
public function __construct() {
$this->middleware('jwt.auth', ['except' => ['login', 'refresh']]);
}
排查过程
- 找到中间件报错位置
问题是// Tymon\JWTAuth\Http\Middleware\BaseMiddleware /** * Attempt to authenticate a user via the token in the request. * * @param \Illuminate\Http\Request $request * * @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException * * @return void */ public function authenticate(Request $request) { $this->checkForToken($request); try { if (! $this->auth->parseToken()->authenticate()) { throw new UnauthorizedHttpException('jwt-auth', 'User not found'); } } catch (JWTException $e) { throw new UnauthorizedHttpException( 'jwt-auth', $e->getMessage(), $e, $e->getCode() ); } }
$this->auth->parseToken()->authenticate()
返回了false
- 继续往下找
此处// Tymon\JWTAuth\JWTAuth /** * Authenticate a user via a token. * * @return \Tymon\JWTAuth\Contracts\JWTSubject|false */ public function authenticate() { $id = $this->getPayload()->get('sub'); if (! $this->auth->byId($id)) { return false; } return $this->user(); }
$this->auth->byId($id)
返回了false
。什么?我的用户ID不存在?什么鬼,继续往下找。 - 继续往下找
明显是这个 Guard 的实例并不是我们想要的,打出来看看他是什么鬼:// Tymon\JWTAuth\Providers\Auth\Illuminate ... use Illuminate\Contracts\Auth\Guard as GuardContract; ... public function __construct(GuardContract $auth) { $this->auth = $auth; } ... /** * Authenticate a user via the id. * @param mixed $id * @return bool */ public function byId($id) { return $this->auth->onceUsingId($id); }
Illuminate\Auth\SessionGuard
,原形毕露,我们的中间件最后使用的 guard 是SessionGuard
。
问题
它调用 SessionGuard
去找的话会查到默认的 user
表中,能有这个ID就有鬼了。
那么,是我哪里搞错了呢?
各位大佬帮帮我,不胜感激
要么默认的guard 改成api
要么中间件增加对应的guard
有配置 User Providers吗 没有的话参考这个配置。
可以在 if 的地方下个断点看auth是哪个类被传进来了,这个类是不是没实现GuardContract接口
我也遇到了这个问题,期待解答
把 guards的api和web的位置换一下试试,api放在first。 参考:docs.spatie.be/laravel-permission/...
试试中间件改成 auth.api
我的配置和你一样的,管理后台用的jwt接口认证,web端用的session。只是中间件使用不一样。
有种解决方法,可以在
jwt.auth
中间件前写一个前置的中间件切换默认guard
,经测试有效路由部分修改为:
Laravel下多模块的认证 之前我自己写的,可以借鉴一下