Django请求无Authorization header,如何正确读取请求的授权头信息
问题原因
你的代码存在两个核心错误导致无法在视图中读取到Authorization头:
- 中间件执行顺序错误:
response = self.get_response(request)是实际触发视图执行的代码,你在这行之后操作的是返回给前端的响应对象,此时视图逻辑已经执行完毕,自然无法在视图中读取到对应的头。 - 操作对象错误:你将Authorization头加在了响应对象上,而不是要传入视图的请求对象上,视图读取的是请求的头,自然拿不到。
修复步骤
- 调整中间件逻辑,在执行视图之前修改请求对象的头信息
class MyMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): # 处理请求的逻辑必须放在get_response之前,执行顺序是:中间件处理请求 -> 执行视图 -> 中间件处理响应 user_id = request.POST.get('created_by', False) try: api_token = CustomUser.objects.get(user=user_id).api_token # Django请求的头信息存储在META字典中,自定义头需要加HTTP_前缀,全大写 request.META['HTTP_AUTHORIZATION'] = f"Bearer {api_token}" except CustomUser.DoesNotExist: pass # 执行视图逻辑 response = self.get_response(request) # 如果不需要给前端返回Authorization头可以删除下面这行 # response['Authorization'] = f"Bearer {api_token}" return response
- 调整视图中读取头的写法,避免无对应头时抛出KeyError
Django 2.2及以上版本推荐使用request.headers快捷读取,不区分大小写:
class MyApiView(mixins.ListModelMixin, viewsets.GenericViewSet): queryset = Event.objects.all() serializer_class = EventSerializer @action(methods=['POST'], detail=False) def post(self, request): # 方式1:推荐写法,不区分大小写,不存在时返回None不会抛错 auth_header = request.headers.get('Authorization') print(auth_header) # 方式2:直接读取META字典 auth_meta = request.META.get('HTTP_AUTHORIZATION') print(auth_meta) tutorial_serializer = MyApiSerializer(data=request.data) if tutorial_serializer.is_valid(): tutorial_serializer.save() return Response(tutorial_serializer.data, status=status.HTTP_201_CREATED) return Response(tutorial_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
- 额外排查场景
如果你的服务部署在Nginx、Apache等反向代理后,需要配置反向代理允许传递Authorization头,否则反向代理会默认丢弃该头,比如Nginx配置中需要添加以下规则:
proxy_pass_request_headers on; proxy_set_header Authorization $http_authorization;
如果是跨域请求场景,需要在CORS配置中添加Authorization到允许的头列表中,否则浏览器会拦截该头的传递。
内容的提问来源于stack exchange,提问作者J maria
相关产品推荐
相关产品推荐

