注销 Django Rest Framework JWT

Logout Django Rest Framework JWT

我想问一下,在我使用 JWT 时注销是否是个好主意。 为了登录,我发送了一个带有用户名和密码的 post 请求以获取所需的令牌(保存到 localStorage 中),当然,这将允许我向需要令牌的视图发送更多请求。

但我不确定应该如何注销用户。我可以清除 localStorage,但令牌仍然可用。

所以,我想问一下我是否应该使用刷新令牌,因为我无法禁用它。

您发布的每个 JWT 都应该有一个到期日期时间,因此每当您注销用户时,您应该从本地存储 cookie 中删除 jwt-token。

but the token remains available.

不确定上面这行是什么意思,但您不必担心从本地存储和 cookie 中清除令牌后用户是否仍然可以使用该令牌,因为无论哪种方式,它都会在到期日期后失效。

你是对的,即使你删除了 JWT 令牌,它在一段时间内仍然有效,直到它过期。 JWT 是无状态的。因此,如果你想处理注销和使令牌无效,你必须需要保留一个数据库或内存缓存来存储无效(列入黑名单的)令牌。然后你需要添加一个新的权限来检查令牌是否被列入黑名单。

class BlackListedToken(models.Model):
    token = models.CharField(max_length=500)
    user = models.ForeignKey(User, related_name="token_user", on_delete=models.CASCADE)
    timestamp = models.DateTimeField(auto_now=True)

    class Meta:
        unique_together = ("token", "user")


class IsTokenValid(BasePermission):
    def has_permission(self, request, view):
        user_id = request.user.id            
        is_allowed_user = True
        token = request.auth.decode("utf-8")
        try:
            is_blackListed = BlackListedToken.objects.get(user=user_id, token=token)
            if is_blackListed:
                is_allowed_user = False
        except BlackListedToken.DoesNotExist:
            is_allowed_user = True
        return is_allowed_user

您可以在令牌到期后将令牌从黑名单中移除。

您无法在令牌创建后手动使其过期。因此,您实际上不能像在会话中那样在服务器端使用 JWT 注销。

JWT 是无状态的,这意味着您应该将所需的一切存储在有效负载中,并跳过对每个请求执行数据库查询。但是如果你打算有一个严格的注销功能,不能等待令牌自动过期,即使你已经从客户端清除了令牌,那么你可能需要忽略无状态逻辑并进行一些查询。那么解决方案是什么?

  • 设置合理的代币到期时间

  • 注销后从客户端删除存储的令牌

  • 针对每个授权请求黑名单查询提供的令牌

黑名单

所有不再有效且尚未过期的令牌的“黑名单”。您可以在文档上使用具有 TTL 选项的数据库,该选项将设置为令牌过期前的剩余时间。

Redis

Redis 是 blacklist 的一个很好的选择,它将允许在内存中快速访问列表。然后,在针对每个授权请求运行的某种中间件中,您应该检查提供的令牌是否在 Blacklist 中。如果是,你应该抛出一个未经授权的错误。如果不是,则放手,JWT 验证将处理它并确定它是否已过期或仍然有效。

有关详细信息,请参阅 How to log out when using JWT。通过 Arpy Vanyan