使用DRF时中间件请求返回匿名用户,求替代修改源码的方案
解决方案
不用改DRF源码,有几个靠谱的办法:
1. 在自定义中间件里手动触发Token认证
DRF的TokenAuthentication本身是个可调用的类,你可以直接在中间件里调用它的认证逻辑,提前把request.user设置好。示例代码:
from rest_framework.authentication import TokenAuthentication from rest_framework.exceptions import AuthenticationFailed from django.http import JsonResponse class YourCustomMiddleware: def __init__(self, get_response): self.get_response = get_response self.auth = TokenAuthentication() def __call__(self, request): # 仅对DRF接口生效,避免干扰普通Django视图 if request.path.startswith('/api/'): auth_header = request.META.get('HTTP_AUTHORIZATION') if auth_header: try: user, token = self.auth.authenticate(request) if user: request.user = user request.auth = token except AuthenticationFailed: # 按业务需求处理认证失败,比如直接返回401 return JsonResponse({'detail': 'Invalid token'}, status=401) response = self.get_response(request) return response
注意要限定作用路径,避免影响非API视图;认证失败的处理可以根据实际需求调整,比如不需要直接拦截就跳过,继续走后续流程。
2. 把中间件逻辑迁移到DRF的权限类
如果你的拦截逻辑是针对接口权限的,完全可以把逻辑放到DRF的自定义权限类里——DRF的认证流程会先于权限检查执行,此时request.user已经是认证后的用户。
示例自定义权限类:
from rest_framework.permissions import BasePermission class YourCustomPermission(BasePermission): def has_permission(self, request, view): # 这里已能拿到认证后的request.user if not request.user.is_authenticated: return False # 你的自定义拦截逻辑,比如检查用户角色、权限标识等 return request.user.has_perm('your_app.some_permission')
然后全局配置到DRF设置中,让所有接口自动生效:
# settings.py REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.TokenAuthentication', ], 'DEFAULT_PERMISSION_CLASSES': [ 'your_app.permissions.YourCustomPermission', ] }
这种方式更贴合DRF的生态,比中间件更适合接口权限场景。
3. 用DRF基类视图统一处理
如果不想全局生效,可以写一个基类视图,把拦截逻辑放到dispatch方法里,让需要检查的业务视图继承这个基类:
from rest_framework.views import APIView from rest_framework.response import Response class BaseAuthenticatedAPIView(APIView): authentication_classes = [TokenAuthentication] def dispatch(self, request, *args, **kwargs): # 先执行父类dispatch完成认证 response = super().dispatch(request, *args, **kwargs) # 在这里添加自定义拦截逻辑,比如请求处理前/后的检查 if not request.user.is_authenticated: return Response({'detail': 'Unauthorized'}, status=401) # 其他业务检查逻辑 return response
后续业务视图只需继承这个基类,就能自动带上认证和拦截逻辑。
内容的提问来源于stack exchange,提问作者Oasis Inc
相关产品推荐
相关产品推荐

