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

Axios请求未向Django服务器发送预期Cookie头问题排查

React 上传文件到 Django 时 CSRF 验证失败的问题解决

问题背景

在 React 应用中使用 Axios 发送 POST 请求向 Django 服务器上传文件,服务器要求请求包含 CSRF Cookie,但尝试了多种设置方式(document.cookie 手动设置、开启 withCredentials: true、指定 Cookie 请求头)均无效。添加 @csrf_exempt 装饰器后请求正常,确认问题出在 CSRF 验证环节。


相关代码片段

Axios 请求代码

const onSubmit = async (data) => {
    const formData = new FormData()
    formData.append('file', data.file[0])

    const csrftoken = getCookie('csrftoken');
    document.cookie = `csrftoken=${csrftoken}`

    const res = await axiosInstance.post('/upload/', formData, {
        timeout: 0,
        headers: {
            'Cookie': `csrftoken=${csrftoken}`, 
            'Content-Type': 'multipart/form-data',
            'x-csrftoken': csrftoken,
        },
        withCredentials: true,
    })

    console.log(res)
}

Django 视图代码

def upload_file(request):
    form = UploadFileForm()
    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES)

        if form.is_valid():
            file_id = save_file_to_database(request.FILES['file'])
            response = JsonResponse({'id': file_id}, status=201)
            return response
        else:
            response = HttpResponse({'message': 'Upload failed'}, status=400)
            return response

    return render(request, 'upload.html', {'form': form})

Django settings.py 配置

CORS_ORIGIN_WHITELIST = (
    "http://localhost:8000",
    "http://127.0.0.1:5173",
)

CSRF_TRUSTED_ORIGINS = [
    "http://127.0.0.1:5173"
]

SESSION_COOKIE_SAMESITE = 'None'

解决方法

1. 修正 CSRF Token 传递逻辑

Django 的 CSRF 验证优先读取 X-CSRFToken 请求头,手动设置 Cookie 头会被浏览器同源策略拦截(浏览器会自动管理 Cookie,手动注入的 Cookie 不被认可)。同时需注意:

  • 移除手动设置 document.cookie 的代码,确保 csrftoken Cookie 是从 Django 服务器正常获取的(提前通过 GET 请求访问 Django 页面或接口)
  • 只保留 X-CSRFToken 请求头,统一为标准大写开头写法
  • 不要手动设置 Content-Type: multipart/form-data,Axios 会自动根据 FormData 生成带边界值的正确头

修改后的 Axios 代码:

const onSubmit = async (data) => {
    const formData = new FormData()
    formData.append('file', data.file[0])

    const csrftoken = getCookie('csrftoken');

    const res = await axiosInstance.post('/upload/', formData, {
        timeout: 0,
        headers: {
            'X-CSRFToken': csrftoken,
        },
        withCredentials: true,
    })

    console.log(res)
}

当前配置缺少关键的跨域凭证允许和 CSRF Cookie 单独设置,补充如下:

CORS_ORIGIN_WHITELIST = (
    "http://localhost:8000",
    "http://127.0.0.1:5173",
)
CORS_ALLOW_CREDENTIALS = True  # 允许跨域请求携带凭证(关键)

CSRF_TRUSTED_ORIGINS = [
    "http://127.0.0.1:5173"
]

SESSION_COOKIE_SAMESITE = 'None'
SESSION_COOKIE_SECURE = True  # 本地 HTTP 开发可临时设为 False,生产环境必须开启
CSRF_COOKIE_SAMESITE = 'None'  # 单独配置 CSRF Cookie 的 SameSite 属性
CSRF_COOKIE_SECURE = True  # 本地 HTTP 开发可临时设为 False

3. 确保 getCookie 函数正确性

使用标准的 Cookie 提取逻辑,避免因函数错误导致无法获取 csrftoken:

function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            const cookie = cookies[i].trim();
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

4. 验证请求头

打开浏览器开发者工具的 Network 标签,检查 POST 请求的 Request Headers:

  • 确认 Cookie 头包含 csrftoken=xxx
  • 确认 X-CSRFToken 头值与 Cookie 中的 csrftoken 一致

若 Cookie 未携带,检查:

  • React 应用域名是否在 CORS_ORIGIN_WHITELIST 和 CSRF_TRUSTED_ORIGINS 中
  • withCredentials: true 是否正确设置
  • 浏览器是否允许第三方 Cookie(本地开发建议用 127.0.0.1 而非 localhost,避免跨域 Cookie 限制)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 15:00:09