You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django自定义中间件排除指定路径配置及request.auth报错排查

问题根因

'WSGIRequest' object has no attribute 'auth' 报错由执行时机错位直接导致:

  • Django中间件的process_view钩子固定在路由匹配完成后、视图函数执行前触发,时机早于视图内部所有逻辑。
  • 如果使用DRF搭配JWT认证,request.auth属性是DRFAPIView在dispatch流程中执行认证组件时才挂载到请求对象上的,process_view执行阶段视图尚未启动,认证逻辑根本没有运行,自然无法获取auth属性。
  • 即使是Django原生视图场景,只要auth属性的挂载逻辑晚于process_view执行时机,都会触发同类报错。
规范的中间件豁免实现方案

该方案和Django原生csrf_exempt实现逻辑一致,无硬编码路由,和路由配置完全解耦,维护性更强。

第一步:实现豁免标记装饰器

# 新建common/decorators.py
from functools import wraps

def token_response_exempt(view_func):
    """标记视图不需要走ExtendTokenResponse中间件逻辑"""
    wrapped = wraps(view_func)(view_func)
    wrapped.token_response_exempt = True
    return wrapped

第二步:调整中间件逻辑

不要把token校验逻辑放到process_view中,改回__call__方法内、视图执行完成的阶段执行,这时候request.auth已经完成挂载,同时可通过路由匹配结果读取视图的豁免标记:

# your_project/middleware.py
from django.utils.deprecation import MiddlewareMixin

class ExtendTokenResponse(MiddlewareMixin):
    def _check_exempt(self, request):
        """校验当前请求匹配的视图是否标记了豁免"""
        resolver_match = getattr(request, 'resolver_match', None)
        if not resolver_match:
            return False
        view_func = resolver_match.func
        # 兼容类视图
        view_class = getattr(view_func, 'view_class', None)
        if view_class:
            if getattr(view_class, 'token_response_exempt', False):
                return True
        # 兼容函数视图、类视图单独方法标记
        return getattr(view_func, 'token_response_exempt', False)

    def __call__(self, request):
        # 先走完整的请求处理链,等所有认证逻辑执行完成
        response = self.get_response(request)
        # 豁免视图直接返回,不执行token处理逻辑
        if self._check_exempt(request):
            return response
        # 这时候request.auth已经挂载完成,可安全执行token校验、刷新逻辑
        if hasattr(request, 'auth') and request.auth:
            # 此处写入原有的token过期判断、刷新、响应头追加新token的业务逻辑
            pass
        return response

第三步:给需要豁免的视图加标记

  • 函数视图直接加装饰器即可:
from common.decorators import token_response_exempt
from django.http import JsonResponse

@token_response_exempt
def logout(request):
    return JsonResponse({"code": 0, "msg": "退出成功"})
  • 类视图使用method_decorator标记:
from django.utils.decorators import method_decorator
from django.views import View
from common.decorators import token_response_exempt

@method_decorator(token_response_exempt, name='dispatch')
class LoginView(View):
    def post(self, request):
        return JsonResponse({"code": 0, "msg": "登录成功"})
注意事项
  • 不推荐硬编码request.path做匹配的核心原因是,后续如果调整路由前缀、增加多语言路径、做版本迭代时,硬编码规则很容易遗漏失效,视图标记的方式和路由完全解耦,不会出现这类问题。
  • 如果确实需要把token校验逻辑放到视图执行前(比如需要提前拦截过期token请求,不让请求打到视图层),必须保证你的ExtendTokenResponse中间件在MIDDLEWARE配置列表中排在所有挂载request.auth的中间件之后;如果是DRF项目,因为认证逻辑在视图层执行,这种场景不适合用中间件做前置校验,建议把逻辑下沉到DRF认证类或权限类中实现。

内容的提问来源于stack exchange,提问作者Dave

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 08:12:47