【问题标题】:Logout Django Rest Framework JWT注销 Django Rest 框架 JWT
【发布时间】:2019-02-25 03:54:03
【问题描述】:

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

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

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

【问题讨论】:

    标签: django django-rest-framework jwt session-state django-rest-framework-jwt


    【解决方案1】:

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

    但令牌仍然可用。

    不确定上述行的含义,但您不必担心在从本地存储和 cookie 中清除令牌后,令牌是否仍可供用户使用,因为无论哪种方式,它都会在过期日期后失效。

    【讨论】:

    • 这个“令牌仍然可用”的问题是,即使在您从会话中注销之后,令牌在特定时间内(在其到期之前)仍然有效。因此有人拥有您的令牌可以成功验证并可以登录系统。这是一个安全流程!
    【解决方案2】:

    您是对的,即使您删除了 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
    

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

    【讨论】:

    • 如果我必须在每次调用时调用数据库,那么差异是什么。 b/w drf token认证,那不是drf token和jwt一样
    【解决方案3】:

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

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

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

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

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

    黑名单

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

    Redis

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

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

    【讨论】:

    • 关于你提到的redis很好,但是redis在内存中,所以如果服务器重新启动,一切都会丢失,并且每个令牌都是有效的
    • @RezaTorkamanAhmadi 如果我们在单独的集群中运行 Redis 会怎样?这样就可以单独维护了,不用担心服务器重启问题。
    • 是的,这也是一个不错的选择。我自己使用 jwt 的自定义方法和有效负载中的查找 id 来解决它,以通过数据库检查进行验证。但是这种 redis 方法可能会快得多。但是这个项目应该是一个很好的规模,因为在中小型项目中,我猜它会给项目带来复杂性
    猜你喜欢
    • 2018-02-06
    • 1970-01-01
    • 2015-10-19
    • 2021-03-09
    • 2015-08-24
    • 2018-04-18
    • 2015-08-13
    • 2018-10-04
    • 2018-11-19
    相关资源
    最近更新 更多