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

向ApiView端点发起AJAX请求触发403 Forbidden错误,如何解决?

解决Django ApiView AJAX PATCH请求403 Forbidden问题

1. 修正AJAX配置的拼写错误

你的代码里header是单数,正确的应该是**headers**(复数),这个拼写错误会导致CSRF Token根本没有被发送到后端,直接触发403:

$.ajax({
    url: '{% url 'edit_custom_user_additional_info' %}',
    method: "patch",
    data: $form.serialize(),
    // 这里改为headers
    headers: {
        "X-CSRFToken": "{{ csrf_token }}"
    },
    success: function (data) {
        alert("Dati aggiuntivi salvati con successo");
    },
    error: function (data) {
        console.log("Errore durante il salvataggio dei dati aggiuntivi");
    },
});

2. 更可靠的CSRF Token获取方式

依赖模板变量{{ csrf_token }}有时候会因为渲染问题失效,建议从浏览器Cookie中直接读取CSRF Token,先定义一个获取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;
}

然后在AJAX中使用:

headers: {
    "X-CSRFToken": getCookie('csrftoken')
},

3. 处理PATCH请求的表单数据格式

$form.serialize()生成的是application/x-www-form-urlencoded格式,而Django REST Framework的ApiView默认对PATCH请求的解析可能需要额外配置。你有两种选择:

  • 改为发送JSON格式数据:
    $.ajax({
        url: '{% url 'edit_custom_user_additional_info' %}',
        method: "patch",
        contentType: "application/json",
        data: JSON.stringify($form.serializeArray().reduce((obj, item) => {
            obj[item.name] = item.value;
            return obj;
        }, {})),
        headers: {
            "X-CSRFToken": getCookie('csrftoken')
        },
        // ... 成功/错误回调
    });
    
    同时在视图中确保使用JSONParser(DRF默认已经包含,但可以显式指定):
    from rest_framework.parsers import JSONParser, FormParser
    
    class EditCustomUserAdditionalInfoView(APIView):
        parser_classes = [JSONParser, FormParser]
        # ... 其他代码
    
  • 保持表单编码格式:确保视图支持application/x-www-form-urlencoded,添加FormParser和MultiPartParser:
    from rest_framework.parsers import FormParser, MultiPartParser
    
    class EditCustomUserAdditionalInfoView(APIView):
        parser_classes = [FormParser, MultiPartParser]
        # ... 其他代码
    

4. 检查视图的认证配置

如果你的ApiView使用了默认的SessionAuthentication,必须确保CSRF Token正确传递。如果不需要会话认证,可以改用TokenAuthentication或其他认证方式:

from rest_framework.authentication import TokenAuthentication

class EditCustomUserAdditionalInfoView(APIView):
    authentication_classes = [TokenAuthentication]
    # ... 其他代码

这种情况下,AJAX请求需要在headers中传递Authorization: Token <你的token>,而不是CSRF Token。

5. 避免滥用csrf_exempt

除非你的接口确实不需要CSRF保护(比如公开的API),否则不要随便给视图加@csrf_exempt,这会带来安全风险。优先修复CSRF Token的传递问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 14:32:21