注销Django Rest框架JWT

注销Django Rest框架JWT,django,django-rest-framework,jwt,session-state,django-rest-framework-jwt,Django,Django Rest Framework,Jwt,Session State,Django Rest Framework Jwt,我想问一下,当我使用JWT时注销是否是个好主意。 为了登录,我发送了一个带有用户名和密码的post请求,以获取所需的令牌(保存到localStorage中),这将允许我向需要令牌的视图发送进一步的请求 但我不确定该如何注销该用户。我可以清除本地存储,但令牌仍然可用 因此,我想问我是否应该使用刷新令牌,因为我无法禁用它。您发出的每个JWT都应该有一个过期日期时间,因此无论何时注销用户,都应该从localstorage cookie中删除JWT令牌 但代币仍然可用 不确定上面这一行的意思,但您不必担

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

但我不确定该如何注销该用户。我可以清除本地存储,但令牌仍然可用


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

您发出的每个JWT都应该有一个过期日期时间,因此无论何时注销用户,都应该从localstorage cookie中删除JWT令牌

但代币仍然可用


不确定上面这一行的意思,但您不必担心在从localstorage和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是无状态的,这意味着您应该将所需的一切存储在有效负载中,并跳过对每个请求执行DB查询。但是,如果您计划使用严格的注销功能,即不能等待令牌自动过期,即使您已经从客户端清除了令牌,那么您可能需要忽略无状态逻辑并执行一些查询。那么什么是解决方案

  • 设置令牌的合理过期时间

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

  • 在每个授权请求中根据黑名单查询提供的令牌

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

雷迪斯 Redis是黑名单的一个很好的选择,它允许对黑名单进行快速内存访问。然后,在对每个授权请求运行的某种中间件中,您应该检查所提供的令牌是否在黑名单中。如果是,您应该抛出未经授权的错误。如果不是,让它去,JWT验证将处理它,并确定它是否过期或仍然有效


有关详细信息,请参阅。Arpy Vanyan

即使在您从会话注销后,此“令牌仍然可用”的问题仍然存在。该令牌在特定的时间段内(在其到期之前)有效。因此,有人拥有您的令牌可以成功验证并登录到系统。这是一个安全流程!关于redis,您提到的很好,但redis在内存中,所以如果服务器重新启动,所有内容都将丢失,并且所有令牌都将丢失valid@RezaTorkamanAhmadi如果我们在单独的集群中运行Redis呢?这样,它将被单独维护,这样我们就不需要担心服务器重启问题。是的,这也是一个很好的选择。我自己使用jwt的自定义方法和有效负载中的查找id来解决这个问题,并通过数据库检查进行验证。但这种redis方法可能要快得多。但是这个项目应该有一个很好的规模,因为在中小型项目中,我想这会给项目带来复杂性。如果每次调用都要调用数据库,那么有什么区别呢?b/w drf令牌身份验证,那么drf令牌和jwt不一样吗