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

Django DRF自定义认证中间件出现accepted_renderer未设置错误如何修复

根因分析

你遇到的AssertionError: .accepted_renderer not set on Response错误核心原因是:DRF的Response对象依赖DRF视图内部的内容协商流程来设置accepted_renderer等必要属性,你在Django原生中间件的process_view阶段直接返回DRF Response,此时还没有进入@api_view/APIView的处理逻辑,Response缺少必要属性,无法正常序列化返回。


修复方案

这里提供两种可行的修复方式,可根据需求选择:

方案1:中间件返回Django原生JsonResponse(改动最小)

直接把中间件里所有返回Response的地方替换为Django原生的JsonResponse,原生响应不需要经过DRF的渲染流程,可直接在中间件层返回。
修改后的中间件代码:

from datetime import datetime
from django.http import JsonResponse # 新增导入

from rest_framework import status

from cheers.core.api.jwt_helpers import decode_cognito_jwt


class CognitoMiddleware(object):
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        return self.get_response(request)

    def process_view(self, request, view_func, view_args, view_kwargs):
        auth = request.headers.get("Authorization", None)
        if not auth:
            return JsonResponse(dict(error='Authorization header expected'), status=status.HTTP_401_UNAUTHORIZED)

        parts = auth.split()

        if parts[0].lower() != "bearer":
            return JsonResponse(dict(error='Authorization header must start with bearer'),
                            status=status.HTTP_401_UNAUTHORIZED)
        elif len(parts) == 1:
            return JsonResponse(dict(error='Token not found'), status=status.HTTP_401_UNAUTHORIZED)
        elif len(parts) > 2:
            return JsonResponse(dict(error='Authorization header must be Bearer token'),
                            status=status.HTTP_401_UNAUTHORIZED)

        token = parts[1]
        try:
            res = decode_cognito_jwt(token)
            expiration = datetime.utcfromtimestamp(res['exp'])
            current_utc = datetime.utcnow()

            if current_utc > expiration:
                return JsonResponse(dict(error=f'current time:{current_utc} is after expiration:{expiration}',
                                     user_msg='Please login again'), status=status.HTTP_400_BAD_REQUEST)

        except Exception:
            # Fail if invalid
            return JsonResponse(dict(error="Invalid JWT"),
                            status=status.HTTP_401_UNAUTHORIZED)
        else:
            # 认证通过,继续进入视图处理
            return None

该方案不需要调整其他代码,直接替换返回类型即可兼容所有视图。


方案2:改为DRF全局认证类(更符合DRF规范)

如果希望统一走DRF的认证流程,更推荐把认证逻辑封装为DRF的认证类,然后全局配置,天然兼容APIView和@api_view装饰的视图:

  1. 新建认证类:
from datetime import datetime
from rest_framework import authentication, exceptions, status
from cheers.core.api.jwt_helpers import decode_cognito_jwt

class CognitoAuthentication(authentication.BaseAuthentication):
    def authenticate(self, request):
        auth = request.headers.get("Authorization", None)
        if not auth:
            raise exceptions.AuthenticationFailed('Authorization header expected')

        parts = auth.split()

        if parts[0].lower() != "bearer":
            raise exceptions.AuthenticationFailed('Authorization header must start with bearer')
        elif len(parts) == 1:
            raise exceptions.AuthenticationFailed('Token not found')
        elif len(parts) > 2:
            raise exceptions.AuthenticationFailed('Authorization header must be Bearer token')

        token = parts[1]
        try:
            res = decode_cognito_jwt(token)
            expiration = datetime.utcfromtimestamp(res['exp'])
            current_utc = datetime.utcnow()

            if current_utc > expiration:
                raise exceptions.AuthenticationFailed(f'current time:{current_utc} is after expiration:{expiration}, Please login again')

        except Exception:
            raise exceptions.AuthenticationFailed("Invalid JWT")
        
        # 认证通过返回用户和token,可根据实际需求构造用户对象
        return (None, res)
  1. 在settings.py中配置全局DRF认证,同时删除原来的中间件配置:
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'cheers.core.api.authentication.CognitoAuthentication', # 替换为实际的认证类路径
    ]
}

# 移除MIDDLEWARE里的CognitoMiddleware配置
MIDDLEWARE = [
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
]

该方案的优势是完全贴合DRF的设计规范,错误响应会自动走DRF的渲染流程,和其他DRF接口的错误格式保持统一。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 00:54:02