我想问一下,在使用 JWT 时注销是否是个好主意。
为了登录,我会发送一个包含用户名和密码的 POST 请求,以获取所需的令牌(保存在 localStorage 中),该令牌将允许我向需要令牌的视图发送进一步的请求。
但我不确定如何注销用户。我可以清除 localStorage,但令牌仍然可用。
因此,我想问一下是否应该刷新令牌,因为我无法禁用它。
但我不确定如何注销用户。我可以清除 localStorage,但令牌仍然可用。
因此,我想问一下是否应该刷新令牌,因为我无法禁用它。
你说得对,即使你删除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
您可以在令牌过期后将其从黑名单列表中移除。实现这个功能的更简单的方法是使用rest_framework_simplejwt
包。我相信您也已经使用了同样的包来生成JWT。
当用户执行注销操作时,您需要从前端清除缓存,并将刷新令牌添加到后端的黑名单中。
访问令牌的生命周期很短,不需要列入黑名单,最好为访问令牌设置最小寿命。这样它们最终会过期。
rest_framework_simplejwt.token_blacklist
默认只会列入刷新令牌的黑名单。
您只需要在settings.py INSTALLED_APPS中添加以下应用程序即可。
INSTALLED_APPS = (
'rest_framework_simplejwt.token_blacklist',
)
还要为TokenBlacklistView
配置urls.py
from rest_framework_simplejwt.views import TokenBlacklistView
urlpatterns = [
...
path('logout/', TokenBlacklistView.as_view(), name='token_blacklist'),
...
]
Source: https://django-rest-framework-simplejwt.readthedocs.io/en/latest/blacklist_app.html