注销Django Rest Framework JWT

yie*_*tem 4 django session-state jwt django-rest-framework django-rest-framework-jwt

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

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

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

a_k*_*k_v 7

没错,即使删除了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
Run Code Online (Sandbox Code Playgroud)

您可以在令牌过期后将其从黑名单中删除。

  • 如果我必须在每次调用时调用数据库,那么有什么区别。黑白 drf 令牌身份验证,那么 drf 令牌和 jwt 不一样吗 (4认同)

Jam*_*yda 7

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

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

  • 为令牌设置合理的到期时间

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

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

黑名单

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

Redis

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

有关更多信息,请参阅如何在使用 JWT 时注销。通过 Arpy Vanyan

  • 关于你提到的redis很棒,但是redis在内存中,所以如果服务器重新启动,一切都会丢失,并且每个令牌都是有效的 (2认同)