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

Django服务端设置Authorization Header无效,求可行实现方案

如何在Django服务端设置Authorization头并完成认证

你遇到的问题核心是认证时机不对:Django的认证中间件(比如你用的TokenAuthentication)是在视图函数执行前就完成运行的。当你在视图里修改request.META['HTTP_AUTHORIZATION']时,认证流程早就结束了,request.user已经被初始化完成,所以这个修改对认证结果完全没有影响。

下面给你两种可行的解决方案,根据你的场景灵活选择:


方案一:自定义认证中间件(推荐)

这种方式最优雅,把认证逻辑放到了请求处理的正确阶段——视图执行前,和Django默认的认证流程完全对齐,适合全局复用。

步骤1:编写中间件

在你的app目录下创建middleware.py文件,添加如下代码:

from django.utils.deprecation import MiddlewareMixin

class CookieTokenMiddleware(MiddlewareMixin):
    def process_request(self, request):
        # 从HttpOnly Cookie中取出token
        token = request.COOKIES.get('token')
        # 如果存在token且当前请求还没有Authorization头,就注入
        if token and not request.META.get('HTTP_AUTHORIZATION'):
            request.META['HTTP_AUTHORIZATION'] = f'Token {token}'

步骤2:注册中间件

在项目的settings.py中,将这个中间件加到MIDDLEWARE列表里,位置要放在TokenAuthentication对应的中间件之前(通常紧跟在AuthenticationMiddleware之后):

MIDDLEWARE = [
    # ... 其他系统中间件 ...
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'your_app_name.middleware.CookieTokenMiddleware',  # 替换成你的app名称
    'rest_framework.authentication.TokenAuthentication',
    # ... 其他中间件 ...
]

步骤3:简化视图代码

现在你可以删掉视图里手动修改request.META的代码了,因为中间件已经提前帮你完成了头注入,认证流程会自动生效:

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def createView(request, *args, **kwargs):
    print(request.user)  # 这里已经是认证后的用户对象
    print(request.headers)
    serializer = TweetPostSerializer(data=request.data)
    if serializer.is_valid():
        serializer.save(user=request.user)
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

方案二:在视图中手动认证

如果你不想修改全局中间件,也可以在单个视图里手动触发认证逻辑,直接更新request.user。

修改你的视图代码如下:

from rest_framework.authentication import TokenAuthentication
from rest_framework.exceptions import AuthenticationFailed

@api_view(['POST'])
# 这里可以暂时去掉@permission_classes([IsAuthenticated]),或者后续手动检查用户状态
def createView(request, *args, **kwargs):
    token = request.COOKIES.get('token')
    if not token:
        return Response({"detail": "Token未在Cookie中找到"}, status=status.HTTP_401_UNAUTHORIZED)
    
    # 手动调用TokenAuthentication的认证方法
    auth_handler = TokenAuthentication()
    try:
        user, auth_token = auth_handler.authenticate_credentials(token)
        # 替换request的用户和认证信息
        request.user = user
        request.auth = auth_token
    except AuthenticationFailed:
        return Response({"detail": "无效的Token"}, status=status.HTTP_401_UNAUTHORIZED)
    
    # 此时request.user已经是认证通过的用户
    print(request.user)
    print(request.headers)
    
    serializer = TweetPostSerializer(data=request.data)
    if serializer.is_valid():
        serializer.save(user=request.user)
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

这种方式的缺点是需要在每个需要认证的视图里重复写认证逻辑,适合临时或特定视图的场景。


再理清楚为什么原来的方法无效

Django的请求处理流程是中间件层 → 视图层,认证中间件属于中间件环节,会优先完成用户认证并设置request.user。你在视图里修改request.META的时候,认证已经结束了,所以这个修改无法回溯影响已经完成的认证结果。

内容的提问来源于stack exchange,提问作者Harrison Austin Osagiede

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:31:30