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

Django JWT认证中间件报错:缺少必需参数'get_response'解决方法

问题解决:Django JWT中间件初始化错误

错误原因

你犯了一个关键错误:把Django中间件注册到了Django REST Framework(DRF)的认证类列表中。DRF的DEFAULT_AUTHENTICATION_CLASSES要求的是继承rest_framework.authentication.BaseAuthentication的认证类,而你的TokenMiddleware是标准的Django中间件,它的__init__方法需要get_response参数,但DRF实例化认证类时会调用无参构造,因此触发TypeError。

另外,你的中间件逻辑存在问题:当前会拦截所有请求,只要没有Bearer Token就直接返回错误,这会导致不需要认证的接口(比如登录、注册)也无法访问。

修复步骤

1. 移除错误的认证类注册

打开settings.py,删除REST_FRAMEWORK中DEFAULT_AUTHENTICATION_CLASSES里的'my_app.middleware.TokenMiddleware':

REST_FRAMEWORK = {
    # 移除错误的认证类注册
    # 'DEFAULT_AUTHENTICATION_CLASSES': [
    #     'my_app.middleware.TokenMiddleware',
    # ],
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        # Add other renderers as needed
    ]
    # Other DRF settings...
}

2. 调整中间件逻辑,允许跳过认证的路径

修改TokenMiddleware,添加不需要认证的路径白名单,比如登录、注册接口:

import jwt
from django.http import JsonResponse
from django.conf import settings
from django.utils.deprecation import MiddlewareMixin


class TokenMiddleware(MiddlewareMixin):
    # 白名单:不需要认证的路径,可根据实际需求修改
    EXEMPT_PATHS = ['/login/', '/register/']

    def __call__(self, request):
        # 检查当前路径是否在白名单中,跳过认证
        if request.path in self.EXEMPT_PATHS:
            return self.get_response(request)

        authorization = request.META.get('HTTP_AUTHORIZATION')

        if authorization and authorization.startswith('Bearer '):
            token = authorization.split(' ')[1]

            try:
                jwks_client = jwt.PyJWKClient(settings.JWT_VERIFY_URL)
                header = jwt.get_unverified_header(token)
                key = jwks_client.get_signing_key(header["kid"]).key
                
                jwt.decode(token, key, algorithms=[header["alg"]])

            except jwt.ExpiredSignatureError:
                return JsonResponse({'error': 'Token has expired'}, status=401)

            except jwt.DecodeError:
                return JsonResponse({'error': 'Token is invalid'}, status=401)
            except Exception as e:
                # 捕获其他JWT相关异常
                return JsonResponse({'error': str(e)}, status=401)
        else:
            return JsonResponse({'message': 'Authentication Bearer Token is required.'}, status=401)

        response = self.get_response(request)
        return response

3. 调整中间件顺序

修改MIDDLEWARE列表,将TokenMiddleware放到跨域中间件之后,避免跨域请求先被拦截:

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "corsheaders.middleware.CorsMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
    "my_app.middleware.TokenMiddleware",
]

更优方案:使用DRF认证类替代中间件

如果是为DRF接口做JWT认证,更推荐遵循DRF的设计规范,编写专属的认证类而非中间件,这样能更好地和DRF的权限控制等功能集成:

import jwt
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from django.conf import settings


class JWTAuthentication(BaseAuthentication):
    def authenticate(self, request):
        authorization = request.META.get('HTTP_AUTHORIZATION')

        if not authorization or not authorization.startswith('Bearer '):
            raise AuthenticationFailed('Authentication Bearer Token is required.')
        
        token = authorization.split(' ')[1]

        try:
            jwks_client = jwt.PyJWKClient(settings.JWT_VERIFY_URL)
            header = jwt.get_unverified_header(token)
            key = jwks_client.get_signing_key(header["kid"]).key
            
            payload = jwt.decode(token, key, algorithms=[header["alg"]])
            # 可根据payload中的信息获取并返回用户对象,比如:
            # user = User.objects.get(id=payload['user_id'])
            # return (user, token)
            return (None, token)  # 无需绑定用户时返回此值

        except jwt.ExpiredSignatureError:
            raise AuthenticationFailed('Token has expired')
        except jwt.DecodeError:
            raise AuthenticationFailed('Token is invalid')
        except Exception as e:
            raise AuthenticationFailed(str(e))

然后在settings.py中注册该认证类:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'my_app.authentication.JWTAuthentication',  # 替换为你的认证类实际路径
    ],
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
    ]
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 22:35:09