使以前的令牌无效并检查用户是不是有 JWT 令牌
Posted
技术标签:
【中文标题】使以前的令牌无效并检查用户是不是有 JWT 令牌【英文标题】:invalidate previous tokens and check a user has JWT token or not使以前的令牌无效并检查用户是否有 JWT 令牌 【发布时间】:2021-08-06 06:25:33 【问题描述】:我有一个带有 Laravel 8 的 API,并使用 JWT 进行身份验证
当我多次登录时,为用户创建了一个新的令牌,但问题是之前创建的令牌是有效且可用的。 (直到令牌过期)
那么我该如何修复这个错误呢?
这是我在 AuthController()
中的 login()
和 createNewToken()
方法:
public function login(Request $request)
$validator = Validator::make($request->all(), [
'email' => 'required|email',
'password' => 'required|string|min:6',
]);
if ($validator->fails())
return response()->json($validator->errors(), 422);
if (! $token = JWTAuth::attempt($validator->validated()))
return response()->json(['error' => 'احراز نشده'], 401);
return $this->createNewToken($token);
protected function createNewToken($token)
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => JWTAuth::factory()->getTTL() * 240,
'user' => auth()->user()
]);
我认为最好的方法是检查登录方法,如果该用户有令牌,则使其无效并创建一个新令牌,否则创建一个新令牌。
但我不知道如何使用 JWT 检查用户令牌
提前感谢您的帮助。
【问题讨论】:
这不是错误,这是 JWT 的工作方式。如果你想要失效,你需要一个黑名单,这基本上是重新引入 JWT 旨在避免的会话问题......在这一点上,你可能最好在 Redis 或其他东西中使用会话。 cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions 【参考方案1】:您可以在登录方法中检查会话。
例如,您可以为会话创建唯一 ID,并将它们设置为您发布的每个令牌的 jti 声明(请参阅here)。您需要将它们存储在某个地方(例如缓存数据存储)。然后,在登录过程中,检查接收到的 JWT 的 jti 是否有效。这样,您可以检查令牌是否被撤销。
但请记住,这会破坏 JTI 的无国籍性质。
【讨论】:
【参考方案2】:使用 JWT 时更好的方法是使用短期访问令牌(例如 5-15 分钟)并使用刷新令牌来获取新令牌,这样用户就不必每 5 分钟登录一次。在这种情况下,您不应该被旧令牌打扰 - 无论如何它只会在几分钟内有效。
如果你真的需要一个选项来“撤销”访问令牌,你应该在验证收到的 JWT 的部分中实现它,而不是登录方法。正如@Deniz 在他的回答中所建议的那样,您将需要一个商店来保存一些可以通过 JWT 的内容进行验证的数据。在 jti
声明中使用会话 ID 是一种有效的选择。另一种选择是在数据库中保留给定用户的最后发布的访问令牌的时间戳,然后验证iat
声明 - 发布于。如果您收到给定用户的令牌,其iat
低于您在数据库中的值,您将拒绝该请求。
无论如何,如果您只想因为有人再次登录而撤销 JWT,那么听起来您想使用会话,而 JWT 不适合会话。只需使用普通的旧饼干即可。
【讨论】:
以上是关于使以前的令牌无效并检查用户是不是有 JWT 令牌的主要内容,如果未能解决你的问题,请参考以下文章
AzureAD JWT 令牌受众声明前缀使 JWT 令牌无效