如何在普通Django视图而非DRF视图中使用djangorestframework-jwt
在普通Django视图中实现JWT身份验证的方案
先直接回答你的核心疑问:djangorestframework-jwt的中间件无法直接用于普通Django视图——它是专门为DRF的视图体系设计的,依赖DRF封装的Request对象和专属认证流程,普通Django视图的HttpRequest对象不会触发它的认证逻辑。
不过你完全可以自己实现类似@login_required的JWT认证装饰器,或者用轻量方式适配DRF的认证能力,下面给你两种可行方案:
方案一:自定义JWT认证装饰器(推荐)
这是最直接可控的方式,手动处理令牌的提取、验证和用户绑定,使用方式和@login_required完全一致。
步骤1:编写自定义装饰器
import jwt from django.http import JsonResponse from django.conf import settings from django.contrib.auth import get_user_model from functools import wraps User = get_user_model() def jwt_required(view_func): @wraps(view_func) def wrapper(request, *args, **kwargs): # 从请求头获取遵循Bearer规范的令牌 auth_header = request.headers.get('Authorization') if not auth_header or not auth_header.startswith('Bearer '): return JsonResponse({'error': '请提供有效的JWT令牌'}, status=401) token = auth_header.split(' ')[1] try: # 解码令牌,验证签名、算法和有效期 payload = jwt.decode( token, settings.SECRET_KEY, algorithms=['HS256'], options={"verify_exp": True} ) # 根据payload中的用户ID获取对应用户 user = User.objects.get(id=payload['id']) # 将用户绑定到request对象,和@login_required效果一致 request.user = user except jwt.ExpiredSignatureError: return JsonResponse({'error': '令牌已过期'}, status=401) except jwt.InvalidTokenError: return JsonResponse({'error': '无效的JWT令牌'}, status=401) except User.DoesNotExist: return JsonResponse({'error': '关联用户不存在'}, status=401) return view_func(request, *args, **kwargs) return wrapper
步骤2:在普通视图中使用装饰器
from django.views.decorators.csrf import csrf_exempt @csrf_exempt @jwt_required def protected_user_data(request): if request.method == 'GET': # 验证通过后,request.user就是当前认证的用户 return JsonResponse({ 'id': request.user.id, 'username': request.user.username, 'email': request.user.email # 假设你的用户模型包含email字段 })
方案二:适配DRF的认证类(可选)
如果你不想自己写解码逻辑,可以在普通视图中手动调用DRF-JWT的认证类,不过需要先把普通HttpRequest转换成DRF的Request对象:
from rest_framework.request import Request from rest_framework_jwt.authentication import JSONWebTokenAuthentication from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt @csrf_exempt def protected_view(request): # 将普通HttpRequest包装成DRF的Request对象 drf_request = Request(request) try: # 使用DRF-JWT的认证类完成令牌验证 user, token = JSONWebTokenAuthentication().authenticate(drf_request) request.user = user except Exception as e: return JsonResponse({'error': str(e)}, status=401) # 验证通过后处理业务逻辑 return JsonResponse({'message': '认证成功', 'username': request.user.username})
这个方案的好处是复用了DRF-JWT的成熟逻辑,但缺点是需要引入DRF的Request对象,对于纯普通Django视图来说有点冗余。
补充说明
- 令牌传递:推荐使用
Authorization: Bearer <token>的请求头方式,比放在URL参数或表单里更安全。 - 自定义装饰器可扩展:比如添加令牌刷新逻辑、支持多种令牌来源、或结合Django的
user_passes_test做权限校验。 - DRF-JWT中间件的局限:它是DRF视图体系的一部分,只会在处理DRF的View类时生效,普通函数视图不会触发它的认证流程,直接加到Django中间件列表里没用。
内容的提问来源于stack exchange,提问作者Santhosh
相关产品推荐
相关产品推荐

