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

Django部署AWS EKS后POST请求报403 CSRF Token未发送问题求助

Django EKS+ALB部署POST请求403 CSRF问题排查方案

问题回顾

基于自定义Docker镜像的Django应用部署在AWS EKS集群(镜像存储于AWS ECR),GET请求正常,但POST请求返回错误:Errore 403 forbidden CSRF Token not sent。已在settings.py中添加CSRF_TRUSTED_ORIGINS配置但未解决问题,使用AWS应用负载均衡器(ALB)作为Ingress,配置如下:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: django
  labels:
    name: django
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/backend-protocol: HTTP
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":80}]'
    alb.ingress.kubernetes.io/group.name: "alta"
    alb.ingress.kubernetes.io/group.order: "2"
    alb.ingress.kubernetes.io/healthcheck-protocol: HTTP
    alb.ingress.kubernetes.io/healthcheck-port: traffic-port
    alb.ingress.kubernetes.io/healthcheck-path: /v1/app
    alb.ingress.kubernetes.io/healthcheck-interval-seconds: "15"
    alb.ingress.kubernetes.io/healthcheck-timeout-seconds: "5"
    alb.ingress.kubernetes.io/success-codes: "200"
    alb.ingress.kubernetes.io/healthy-threshold-count: "2"
    alb.ingress.kubernetes.io/unhealthy-threshold-count: "2"
spec:
  ingressClassName: alb
  rules:
    - http:
        paths:
          - pathType: Prefix
            path: /
            backend:
              service:
                name: djangoapp-cluster-ip
                port:
                  number: 80

排查步骤&解决方案

1. 核对CSRF_TRUSTED_ORIGINS格式正确性

Django 2.2版本中,CSRF_TRUSTED_ORIGINS必须包含完整协议+域名(带端口需一并添加)。例如你的ALB公网域名为my-alb-123456789.us-east-1.elb.amazonaws.com,配置应为:

CSRF_TRUSTED_ORIGINS = ['http://my-alb-123456789.us-east-1.elb.amazonaws.com']

若ALB启用HTTPS,需将协议改为https://,遗漏协议是常见的配置错误。

2. 配置ALB传递反向代理请求头

ALB作为反向代理,需向Django传递X-Forwarded-Proto和X-Forwarded-Host头,确保Django识别真实请求来源。在Ingress的annotations中添加以下配置:

alb.ingress.kubernetes.io/forward-headers: "X-Forwarded-Proto,X-Forwarded-Host"
alb.ingress.kubernetes.io/headers: |
    X-Forwarded-Proto: "$scheme"
    X-Forwarded-Host: "$host"

同时在Django的settings.py中开启反向代理支持:

USE_X_FORWARDED_HOST = True
# 若ALB使用HTTPS,添加以下配置
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

3. 确认CSRF Token传递逻辑

  • 普通表单提交:确保模板中添加{% csrf_token %}标签,该标签会生成隐藏token字段,供Django自动校验。
  • DRF接口请求:
    • 使用Session认证时,请求头需携带X-CSRFToken,值为Cookie中的csrftoken。
    • 使用Token/JWT认证时,可直接在DRF配置中关闭CSRF验证(API场景无需Session级CSRF防护):
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
        # 移除SessionAuthentication(若不需要)
    ]
}

若需同时支持两种认证,可给无需CSRF校验的视图添加@csrf_exempt装饰器。

4. 检查Django中间件顺序

CsrfViewMiddleware必须放在SessionMiddleware之后,否则CSRF Token无法与Session关联。settings.py中的中间件顺序需满足:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',  # 必须位于SessionMiddleware之后
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

5. 打印请求头排查真实来源

在Django中添加调试视图,打印请求头确认Django接收的域名和协议是否正确:

from django.http import HttpResponse

def debug_request(request):
    print(f"HTTP_HOST: {request.META.get('HTTP_HOST')}")
    print(f"X_FORWARDED_HOST: {request.META.get('HTTP_X_FORWARDED_HOST')}")
    print(f"X_FORWARDED_PROTO: {request.META.get('HTTP_X_FORWARDED_PROTO')}")
    return HttpResponse("调试信息已打印至日志")

访问该视图后,查看日志字段是否与ALB的域名、协议一致,不一致则说明ALB请求头未正确传递。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 21:25:23