向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
相关产品推荐
相关产品推荐

