16

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

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

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

4

3 回答 3

16

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

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

于 2018-09-21T03:40:32.363 回答
9

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

JWT is stateless, meaning that you should store everything you need in the payload and skip performing a DB query on every request. But if you plan to have a strict log out functionality, that cannot wait for the token auto-expiration, even though you have cleaned the token from the client-side, then you might need to neglect the stateless logic and do some queries. so what's a solution?

  • Set a reasonable expiration time on tokens

  • Delete the stored token from client-side upon log out

  • Query provided token against The Blacklist on every authorized request

The Blacklist

“Blacklist” of all the tokens that are valid no more and have not expired yet. You can use a DB that has TTL option on documents that would be set to the amount of time left until the token is expired.

Redis

Redis is a good option for blacklist, which will allow fast in-memory access to the list. Then, in the middleware of some kind that runs on every authorized request, you should check if the provided token is in The Blacklist. If it is you should throw an unauthorized error. And if it is not, let it go and the JWT verification will handle it and identify if it is expired or still active.

For more information, see How to log out when using JWT. by Arpy Vanyan

于 2018-12-22T09:27:42.923 回答
3

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

但令牌仍然可用。

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

于 2018-09-20T19:23:08.487 回答