dingo/api 和 jwt-auth 中无法使用无效令牌错误进行身份验证
Unable to authenticate with invalid token error in dingo/api with jwt-auth
我正在使用 dingo/api (that has built-in support for jwt-auth) 制作 API。
假设这是我的路线:
$api->group(['prefix' => 'auth', 'namespace' => 'Auth'], function ($api) {
$api->post('checkPhone', 'LoginController@checkPhone');
//Protected Endpoints
$api->group(['middleware' => 'api.auth'], function ($api) {
$api->post('sendCode', 'LoginController@sendCode');
$api->post('verifyCode', 'LoginController@verifyCode');
});
});
checkPhone
具有授权和创建令牌任务的方法如下:
public function checkPhone (Request $request)
{
$phone_number = $request->get('phone_number');
if (User::where('phone_number', $phone_number)->exists()) {
$user = User::where('phone_number', $phone_number)->first();
$user->injectToken();
return $this->response->item($user, new UserTransformer);
} else {
return $this->response->error('Not Found Phone Number', 404);
}
}
和 User
模型上的 injectToken()
方法是:
public function injectToken ()
{
$this->token = JWTAuth::fromUser($this);
return $this;
}
令牌创建工作正常。
但是当我将它发送到受保护的端点时,总是 Unable to authenticate with invalid token
发生。
受保护的端点操作方法是:
public function verifyCode (Request $request)
{
$phone_number = $request->get('phone_number');
$user_code = $request->get('user_code');
$user = User::wherePhoneNumber($phone_number)->first();
if ($user) {
$lastCode = $user->codes()->latest()->first();
if (Carbon::now() > $lastCode->expire_time) {
return $this->response->error('Code Is Expired', 500);
} else {
$code = $lastCode->code;
if ($user_code == $code) {
$user->update(['status' => true]);
return ['success' => true];
} else {
return $this->response->error('Wrong Code', 500);
}
}
} else {
return $this->response->error('User Not Found', 404);
}
}
我使用 PostMan
作为 API 客户端并将生成的令牌作为 header 发送,如下所示:
Authorization:Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI5ODkxMzk2MTYyNDYiLCJpc3MiOiJodHRwOlwvXC9hcGkucGFycy1hcHAuZGV2XC92MVwvYXV0aFwvY2hlY2tQaG9uZSIsImlhdCI6MTQ3NzEyMTI0MCwiZXhwIjoxNDc3MTI0ODQwLCJuYmYiOjE0NzcxMjEyNDAsImp0aSI6IjNiMjJlMjUxMTk4NzZmMzdjYWE5OThhM2JiZWI2YWM2In0.EEj32BoH0URg2Drwc22_CU8ll--puQT3Q1NNHC0LWW4
我在网络和相关存储库中多次搜索后找不到解决方案。
您认为问题是什么?
更新:
我发现 laravel 提供的 loginController 的构造函数未发现错误:
public function __construct ()
{
$this->middleware('guest', ['except' => 'logout']);
}
因为当我评论 $this->middleware('guest', ['except' => 'logout']);
时一切正常。
但是如果我删除这条线是正确的吗?
API 的这一行应该如何?
正如我之前提到的更新说明问题,我在 LoginController 中使用了 checkPhone
和 verifyCode
,它在其构造函数中检查了来宾。
并且因为 guest
中间件引用 \App\Http\Middleware\RedirectIfAuthenticated::class
并且将登录用户重定向到 /home
目录并且我没有创建它,所以 404 error
发生了。
现在,我将这些方法移到了 UserController
中,其构造函数中没有任何中间件。
将我的 config/api.php 更新到这个就成功了
// config/api.php
...
'auth' => [
'jwt' => 'Dingo\Api\Auth\Provider\JWT'
],
...
始终值得通读源代码以了解发生了什么。回答:需要身份验证提供者的标识符才能检索用户。
/**
* Authenticate request with a JWT.
*
* @param \Illuminate\Http\Request $request
* @param \Dingo\Api\Routing\Route $route
*
* @return mixed
*/
public function authenticate(Request $request, Route $route)
{
$token = $this->getToken($request);
try {
if (! $user = $this->auth->setToken($token)->authenticate()) {
throw new UnauthorizedHttpException('JWTAuth', 'Unable to authenticate with invalid token.');
}
} catch (JWTException $exception) {
throw new UnauthorizedHttpException('JWTAuth', $exception->getMessage(), $exception);
}
return $user;
}
我正在使用 dingo/api (that has built-in support for jwt-auth) 制作 API。
假设这是我的路线:
$api->group(['prefix' => 'auth', 'namespace' => 'Auth'], function ($api) {
$api->post('checkPhone', 'LoginController@checkPhone');
//Protected Endpoints
$api->group(['middleware' => 'api.auth'], function ($api) {
$api->post('sendCode', 'LoginController@sendCode');
$api->post('verifyCode', 'LoginController@verifyCode');
});
});
checkPhone
具有授权和创建令牌任务的方法如下:
public function checkPhone (Request $request)
{
$phone_number = $request->get('phone_number');
if (User::where('phone_number', $phone_number)->exists()) {
$user = User::where('phone_number', $phone_number)->first();
$user->injectToken();
return $this->response->item($user, new UserTransformer);
} else {
return $this->response->error('Not Found Phone Number', 404);
}
}
和 User
模型上的 injectToken()
方法是:
public function injectToken ()
{
$this->token = JWTAuth::fromUser($this);
return $this;
}
令牌创建工作正常。
但是当我将它发送到受保护的端点时,总是 Unable to authenticate with invalid token
发生。
受保护的端点操作方法是:
public function verifyCode (Request $request)
{
$phone_number = $request->get('phone_number');
$user_code = $request->get('user_code');
$user = User::wherePhoneNumber($phone_number)->first();
if ($user) {
$lastCode = $user->codes()->latest()->first();
if (Carbon::now() > $lastCode->expire_time) {
return $this->response->error('Code Is Expired', 500);
} else {
$code = $lastCode->code;
if ($user_code == $code) {
$user->update(['status' => true]);
return ['success' => true];
} else {
return $this->response->error('Wrong Code', 500);
}
}
} else {
return $this->response->error('User Not Found', 404);
}
}
我使用 PostMan
作为 API 客户端并将生成的令牌作为 header 发送,如下所示:
Authorization:Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI5ODkxMzk2MTYyNDYiLCJpc3MiOiJodHRwOlwvXC9hcGkucGFycy1hcHAuZGV2XC92MVwvYXV0aFwvY2hlY2tQaG9uZSIsImlhdCI6MTQ3NzEyMTI0MCwiZXhwIjoxNDc3MTI0ODQwLCJuYmYiOjE0NzcxMjEyNDAsImp0aSI6IjNiMjJlMjUxMTk4NzZmMzdjYWE5OThhM2JiZWI2YWM2In0.EEj32BoH0URg2Drwc22_CU8ll--puQT3Q1NNHC0LWW4
我在网络和相关存储库中多次搜索后找不到解决方案。
您认为问题是什么?
更新:
我发现 laravel 提供的 loginController 的构造函数未发现错误:
public function __construct ()
{
$this->middleware('guest', ['except' => 'logout']);
}
因为当我评论 $this->middleware('guest', ['except' => 'logout']);
时一切正常。
但是如果我删除这条线是正确的吗?
API 的这一行应该如何?
正如我之前提到的更新说明问题,我在 LoginController 中使用了 checkPhone
和 verifyCode
,它在其构造函数中检查了来宾。
并且因为 guest
中间件引用 \App\Http\Middleware\RedirectIfAuthenticated::class
并且将登录用户重定向到 /home
目录并且我没有创建它,所以 404 error
发生了。
现在,我将这些方法移到了 UserController
中,其构造函数中没有任何中间件。
将我的 config/api.php 更新到这个就成功了
// config/api.php
...
'auth' => [
'jwt' => 'Dingo\Api\Auth\Provider\JWT'
],
...
始终值得通读源代码以了解发生了什么。回答:需要身份验证提供者的标识符才能检索用户。
/**
* Authenticate request with a JWT.
*
* @param \Illuminate\Http\Request $request
* @param \Dingo\Api\Routing\Route $route
*
* @return mixed
*/
public function authenticate(Request $request, Route $route)
{
$token = $this->getToken($request);
try {
if (! $user = $this->auth->setToken($token)->authenticate()) {
throw new UnauthorizedHttpException('JWTAuth', 'Unable to authenticate with invalid token.');
}
} catch (JWTException $exception) {
throw new UnauthorizedHttpException('JWTAuth', $exception->getMessage(), $exception);
}
return $user;
}