Django AJAX POST请求403错误:CSRF验证失败解决方案与原理分析
本文详解Django中使用AJAX发送POST请求时遇到的403 CSRF验证失败问题。通过分析官方JS解决方案与手动提取token两种方法,指出核心在于HTML中必须保留{% csrf_token %}以生成浏览器cookie。即使使用简化JS代码,若清除Cookie导致csrftoken丢失仍会报错,掌握token传递机制即可彻底解决该问题。
Django AJAX POST请求403错误:CSRF验证失败解决方案与原理分析
前言
问题背景与常见误区
在近期学习Django框架的过程中,尝试通过AJAX向后端发送POST请求时,直接收到了403错误提示,指出CSRF验证失败。此前在使用Django模板渲染页面时,只需在模板中添加{% csrf_token %}标签即可自动处理CSRF保护;然而,当采用AJAX方式发送POST请求时,这种传统的模板处理方式便不再直接生效。
文章末尾提供了更为简便的解决思路,前文所述方法相对繁琐。
官方JS解决方案与注意事项
经查阅网络资料及参考多位博主的经验,发现Django官方文档中其实已有明确的解决指引。其基本处理流程如下:
具体操作是新建一个JavaScript文件,将网络上提供的解决代码粘贴其中,然后在需要使用AJAX的页面中引入该JS文件。需要注意的是,如果所找的解决代码依赖于jQuery,则必须确保在引入jQuery库之后再引入该解决代码(因为网络上的解决方案众多,既有原生JS版本也有基于jQuery的版本,顺序至关重要)。
文末附上了本人使用的JS相关代码,读者也可自行搜索其他方案。
如果上述常规方法未能解决你的问题,那么你可能和我遇到了同一个隐蔽的陷阱。
深层原因:Cookie与Token的依赖关系
虽然应用上述方法后问题一度解决,但随着我对代码进行多次修改并清除了相关页面的Cookie,甚至在休息片刻后重新运行程序时,403 CSRF错误再次出现。百思不得其解之际,我重新查阅了Django官方文档的相关部分,经过大量英文阅读后大致定位了问题根源。
我发现自己在HTML页面中删除了原本添加的{% csrf_token %}标签,加之手动清除了浏览器中的相关Cookie,导致csrftoken被彻底清除。此时刷新页面,HTML源码中已找不到{% csrf_token %},浏览器中也不存在csrftoken的Cookie值。在这种情况下,即便引入了相关的JS代码,也无法发挥作用。
打个比方:
- 吃饭需要工具,即筷子,但如果连饭都没有,拿着筷子又能吃什么呢?
- 这里的“筷子”指的是用于解决CSRF问题的JS代码,而“饭”则是HTML中的{% csrf_token %}标签,更准确地说,是浏览器中生成的名为csrftoken的Cookie。
- 只有两者同时存在,才能彻底解决CSRF验证问题。
总结要点如下:
- 在使用AJAX发送POST请求时,HTML页面中必须包含{% csrf_token %}标签,通常放置在body标签内即可满足要求。
- 随后引入相应的JS解决代码。
- 补充说明:此方法与是否使用表单关系不大,因为我的HTML页面中并未使用表单,而是直接通过点击按钮触发AJAX请求。

相关JS代码示例
需要引入的相关JS代码
$(document).ajaxSend(function(event, xhr, settings) {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// 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;
}
function sameOrigin(url) {
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
function safeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
});
更简洁的手动传递Token方法
简单方法
- 首先,在你需要发起AJAX POST请求的页面任意位置添加{% csrf_token %}标签。
- 接着在浏览器中查看页面源码,会发现一个隐藏输入标签:<input type="hidden" name="csrfmiddlewaretoken" value="jlYb5LCP21TxGapw7OuO0xbHmRnyFzlgDapiDl1M1Vp6dOjPM4BlHOgOVeuPYQ27">。
- 在发起AJAX POST请求并构建JSON参数时,采用以下方式将其作为参数传递。前两个参数为自定义内容,请自行忽略;键值对中的键名应为隐藏输入标签的name属性值,值则为其value属性值。
- csrf = $('input[name="csrfmiddlewaretoken"]').val();
- params = {'sku_id': sku_id, 'count': count, 'csrfmiddlewaretoken': csrf};
- 通过这种方式将csrf参数传递给后端,即可避免403错误。相比前文使用的大段JS代码,这种方法要简洁得多。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









