如何在Django REST框架中使用Simple JWT实现JWT令牌黑名单?
实现Simple JWT令牌黑名单与注销功能
嘿,我刚好之前在Django REST项目里折腾过这个功能,给你一步步拆解,附上完整代码示例,轻松搞定令牌黑名单和注销需求:
1. 先配置黑名单应用
首先要把Simple JWT自带的黑名单应用加到项目里,修改settings.py:
INSTALLED_APPS = [ # 你的其他应用... 'rest_framework', 'rest_framework_simplejwt', 'rest_framework_simplejwt.token_blacklist', # 新增这个黑名单应用 ]
然后执行数据库迁移,创建OutstandingToken和BlacklistedToken两张核心表:
python manage.py migrate
2. 配置Simple JWT参数
在settings.py里补充Simple JWT的配置,确保黑名单功能正常生效:
from datetime import timedelta SIMPLE_JWT = { "ACCESS_TOKEN_LIFETIME": timedelta(minutes=5), # 按需调整有效期 "REFRESH_TOKEN_LIFETIME": timedelta(days=1), "ROTATE_REFRESH_TOKENS": True, # 开启刷新令牌轮换机制 "BLACKLIST_AFTER_ROTATION": True, # 轮换后自动拉黑旧的刷新令牌 "AUTH_HEADER_TYPES": ("Bearer",), }
这里的
ROTATE_REFRESH_TOKENS和BLACKLIST_AFTER_ROTATION组合起来,能防止用户重复使用旧的刷新令牌,进一步提升接口安全性。
3. 实现注销接口(核心代码)
Simple JWT默认没有提供注销接口,我们自己写一个视图来处理注销时的令牌拉黑逻辑:
在你的app的views.py里添加:
from rest_framework import status from rest_framework.response import Response from rest_framework.views import APIView from rest_framework_simplejwt.tokens import RefreshToken from rest_framework.permissions import IsAuthenticated class LogoutView(APIView): # 只有已登录用户才能访问注销接口 permission_classes = [IsAuthenticated] def post(self, request): try: # 从请求体中获取前端传来的refresh令牌 refresh_token = request.data["refresh"] # 初始化RefreshToken对象 token = RefreshToken(refresh_token) # 调用blacklist()方法,自动将该令牌加入黑名单 token.blacklist() return Response(status=status.HTTP_205_RESET_CONTENT) except Exception as e: # 如果令牌无效或者格式错误,返回错误信息 return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
然后在项目的urls.py里配置这个注销接口的路由:
from django.urls import path from .views import LogoutView # 替换成你实际的视图路径 urlpatterns = [ # 你的其他路由... path('api/logout/', LogoutView.as_view(), name='api-logout'), ]
4. 后台手动拉黑令牌(可选操作)
如果你需要在管理员后台手动处理令牌,迁移数据库后,Django admin会自动出现Outstanding Tokens和Blacklisted Tokens两个菜单:
- 先在
Outstanding Tokens里找到要拉黑的令牌记录 - 点击进入该记录,然后点击页面右上角的"Add Blacklisted Token",关联这条OutstandingToken即可完成拉黑
测试验证
前端在注销时,只需把用户持有的refresh令牌以POST请求发送到/api/logout/接口,后端就会自动把这个令牌加入黑名单,之后该refresh令牌就无法再用来获取新的access令牌了。
内容的提问来源于stack exchange,提问作者qwertzuiop




