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

Django项目提交表单出现403 Forbidden错误(CSRF令牌问题)

解决Django中JS提交表单的CSRF 403错误

核心问题分析

你遇到的问题核心在于CSRF令牌的获取与传递逻辑错误,尤其是JS动态生成HTML场景下,模板标签未被正确解析、令牌未与Cookie同步,以及fetch请求未携带凭证这几个关键点。

分步解决方案

1. 正确获取CSRF令牌(避免模板标签未解析)

由于你用JS生成HTML,直接在JS代码里写{{ csrf_token }}不会被Django模板引擎解析,拿到的只是字符串而非实际令牌。正确做法是:

  • 在Django渲染的主HTML文件(比如base.html)中,提前将令牌存入全局变量:
    <script>
        window.csrfToken = '{{ csrf_token }}';
    </script>
    
    主模板会被Django解析,这里的{{ csrf_token }}会自动替换为当前会话的有效令牌。

2. 动态生成表单时添加有效令牌字段

不要硬编码令牌值,而是用全局变量动态插入隐藏字段:

// 假设你正在用JS生成表单
const form = document.createElement('form');
form.addEventListener('submit', apiSendDataUser);

// 添加CSRF隐藏字段
const csrfInput = document.createElement('input');
csrfInput.type = 'hidden';
csrfInput.name = 'csrfmiddlewaretoken';
csrfInput.value = window.csrfToken; // 使用全局变量的有效令牌
form.appendChild(csrfInput);

// 添加其他表单字段(邮箱、用户名、密码等)
// ...

3. 调整fetch请求配置(确保携带凭证)

fetch默认不会携带Cookie,而Django的CSRF验证需要比对请求中的令牌与Cookie中的令牌是否一致,因此必须添加credentials: 'include':

const apiSendDataUser = (event) => {
    event.preventDefault();
    
    const formData = new FormData(event.target);
    fetch('https://127.0.0.1:8000/myProject/post_user',{
        method: 'POST',
        body: formData,
        credentials: 'include' // 关键:携带Cookie用于CSRF验证
    })
    .then(response => {
        if (response.ok) {
            return response.json();
        } else {
            throw new Error('Error: ' + response.status);
        }
    })
    .then(data => {
        console.log(data);
    })
    .catch(error => {
        console.error(error);
    });
};

说明:如果表单中已经正确包含csrfmiddlewaretoken字段,FormData会自动携带该参数,无需再在headers中手动添加X-CSRFToken。

4. 备选方案:从Cookie中直接获取令牌

如果动态生成表单的场景复杂,也可以直接从Cookie中提取CSRF令牌,无需依赖表单字段:

// 工具函数:从Cookie中获取指定值
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;
}

// 修改fetch请求逻辑
const apiSendDataUser = (event) => {
    event.preventDefault();
    
    const csrfToken = getCookie('csrftoken');
    const formData = new FormData(event.target);
    fetch('https://127.0.0.1:8000/myProject/post_user',{
        method: 'POST',
        body: formData,
        headers: {
            'X-CSRFToken': csrfToken
        },
        credentials: 'include'
    })
    .then(response => {
        // ... 后续逻辑不变
    })
    // ...
};

5. 后端配置检查

确保你的Django项目settings.py中启用了CSRF中间件:

MIDDLEWARE = [
    # ... 其他中间件
    'django.middleware.csrf.CsrfViewMiddleware',
    # ...
]

如果是跨域场景(比如前端运行在8080端口,后端在8000),需安装并配置django-cors-headers:

  • 安装:pip install django-cors-headers
  • 添加到INSTALLED_APPS和MIDDLEWARE
  • 设置:
    CORS_ALLOW_CREDENTIALS = True
    CORS_ORIGIN_WHITELIST = [
        'http://localhost:8080', # 你的前端域名/端口
    ]
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 11:22:17