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

能否从JavaScript向Django API发送CSRF Cookie-Token?跨域POST遇403错误

问题描述

我有一个基于Svelte框架开发、Netlify部署的SAP应用,业务逻辑和数据处理依赖Django后端。之前只用GET请求一切正常,但现在需要上传文件并使用POST请求,发送POST请求到Django时收到403错误,错误日志如下:

WARNING:django.security.csrf:Forbidden (Origin checking failed - http://localhost:8888 does not match any trusted origins.): /test-put/

我已经处理了CORS相关配置,但还是遇到这个问题。

前端调用代码(JavaScript)

async function sendDataToAPI(payload) {
    let endpoint = 'http://192.168.4.28:8000/test-put/'
    const form_data = new FormData();

    form_data.append("payload", payload);

    await fetch(endpoint, {
        credentials: "same-origin",
        method: "POST",
        body: JSON.stringify({
            data: payload,
        }),
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
            "X-CSRFToken": getCookie("csrftoken"),
        },
    })
    .then((response) => response.json())
    .then((result) => {
        console.log("Success:", result);
    })
    .catch((error) => {
        console.error("Error:", error);
    });
}


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();
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

Django 路由配置(urls.py)

path('test-put/', views.TestPut.as_view()),

Django 视图代码(views.py)

class TestPut(View):
    def put(self, request):
        return {}

核心疑问

由于发起请求的页面不是Django模板,这种场景下实现POST请求是否可行?该如何解决这个403错误?


解决方案

1. 解决跨域信任源问题

错误日志明确提示Origin checking failed,说明Django未将前端域名加入可信源。在Django的settings.py中添加配置:

ALLOWED_HOSTS = ['192.168.4.28', 'localhost', '你的Netlify线上域名']
CSRF_TRUSTED_ORIGINS = [
    'http://localhost:8888',
    'https://你的Netlify线上域名',
    'http://192.168.4.28:8000'
]

注意:Django 3.2及以上版本必须通过CSRF_TRUSTED_ORIGINS配置跨域可信源,仅靠CORS插件无法解决CSRF的源校验问题。

2. 修正前后端请求/响应匹配问题

  • 前端代码中创建了FormData但未实际使用,若要上传文件,应直接将FormData作为请求体,且不要手动设置Content-Type(浏览器会自动添加正确的边界标识)。
  • 跨域请求需携带Cookie(包括CSRF Token),因此credentials需设为"include"而非"same-origin"。
  • 原Django视图仅实现了put方法,但前端发送的是POST请求,会导致405方法不允许,需修改视图支持POST:

修正后的前端代码

async function sendDataToAPI(payload, file) {
    let endpoint = 'http://192.168.4.28:8000/test-put/'
    const form_data = new FormData();

    form_data.append("payload", payload);
    if (file) {
        form_data.append("file", file); // 添加待上传的文件
    }

    await fetch(endpoint, {
        credentials: "include",
        method: "POST",
        body: form_data,
        headers: {
            'Accept': 'application/json',
            "X-CSRFToken": getCookie("csrftoken"),
        },
    })
    .then((response) => response.json())
    .then((result) => {
        console.log("Success:", result);
    })
    .catch((error) => {
        console.error("Error:", error);
    });
}

修正后的Django视图

from django.http import JsonResponse

class TestPut(View):
    def post(self, request):
        # 从FormData中获取数据
        payload = request.POST.get('payload')
        uploaded_file = request.FILES.get('file')
        # 编写你的业务处理逻辑
        return JsonResponse({'status': 'success', 'message': '数据接收成功'})

3. 非Django模板页面的CSRF Token获取方案

因为前端不是Django模板,无法使用{% csrf_token %},可通过两种方式获取Token:

  • 方案一:新增Django接口返回Token
# urls.py
path('get-csrf-token/', views.get_csrf_token),

# views.py
from django.middleware.csrf import get_token
from django.http import JsonResponse

def get_csrf_token(request):
    return JsonResponse({'csrfToken': get_token(request)})

前端先调用该接口获取Token,再在POST请求中携带。

  • 方案二:确保Cookie正常传递
    在Django的settings.py中开启CORS允许携带Cookie:
CORS_ALLOW_CREDENTIALS = True

这样前端的getCookie函数就能从Django设置的Cookie中拿到CSRF Token。

4. 确认CORS配置完整性

确保django-cors-headers的配置正确:

INSTALLED_APPS = [
    ...
    'corsheaders',
    ...
]

MIDDLEWARE = [
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    ...
]

CORS_ALLOWED_ORIGINS = [
    'http://localhost:8888',
    'https://你的Netlify线上域名',
]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 18:47:18