Django中ajax发送post请求,报403错误CSRF验证失败解决办法
今天学习Django框架,⽤ajax向后台发送post请求,直接报了403错误,说CSRF验证失败;先前⽤模板的话都是在⾥⾯加⼀个 {% csrf_token %} 就直接搞定了CSRF的问题了;很显然,⽤ajax发送post请求这样就⽩搭了;
⽂末已经更新更简单的⽅法,上⾯的略显⿇烦
上⽹上查了⼀下,看了⼏个别⼈的博客,才知道官⽹也早有说明解决办法,⼤致流程就是:
就是新建⼀个JavaScript⽂件,然后把⽹上给的代码粘贴进去,然后在你使⽤ajax的页⾯把它引⼊⼀下;当然,如果你在⽹上到的解决代码包含JQuery的话,那就需要在引⼊的JQuery之后引⼊了(毕竟解决代码不唯⼀,⽹上⼀⼀堆,基本都是对的,原⽣JS和带JQuery的都有);
⽂末会附上我使⽤的JS相关代码,也可以去⽹上!
如果上述没有解决你的问题,那就说明你和我踩了同样的⼀个⼩坑........
⽤了上⾯查到的⽅法,直接就解决了我的问题,但是随着我对代码修修改改、清除了相关页⾯的cookie,吃个饭再运⾏,竟然⼜报403的CSRF错误了;百思不得其解的我⼜去Django官⽹看了⼀下相关部分的⽂档,⼀堆英⽂看看⼤概到了问题;
我发现我把html页⾯⾥⾯原先加的 {% csrf_token %} 这个东西给删掉了,加上⾕歌的相关页⾯cookie被我⼀清除,csrftoken就被咔嚓了,再刷新页⾯,去html页⾯⾥也不到 {% csrf_token %} ,没有了csrftoken那个cookie值,即使有相关的JS代码也⽑⽤没有了;
打个⽐⽅:
你吃饭需要⼯具,也就是筷⼦,但是饭都没有,你拿个筷⼦吃什么呀
这⾥的筷⼦就是解决问题的JS代码,⽽饭就是这个 {% csrf_token %} ,更确切说因该是浏览器中的叫 csrftoken 的 cookie;
两者都有了,才能彻底解决吃饭的问题;
总结下来:
使⽤ajax发送post请求时,html页⾯⾥⼀定要有 {% csrf_token %},在body⾥应该就没什么⼤问题;
然后引⼊相关的JS解决代码;
补充⼀下,和表单没什么太⼤关系,因为我的html页⾯⾥就没有表单,直接通过点击按钮发送的ajax请求;
需要引⼊的相关JS代码
1 $(document).ajaxSend(function(event, xhr, settings) {
2function getCookie(name) {
3var cookieValue = null;
4if (kie && kie != '') {
5var cookies = kie.split(';');
6for (var i = 0; i < cookies.length; i++) {
7var cookie = im(cookies[i]);
8// Does this cookie string begin with the name we want?
9if (cookie.substring(0, name.length + 1) == (name + '=')) {
10                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
11break;
发送ajax请求的步骤12                }
13            }
14        }
15return cookieValue;
16    }
17function sameOrigin(url) {
18// url could be relative or scheme relative or absolute
19var host = document.location.host; // host + port
20var protocol = document.location.protocol;
21var sr_origin = '//' + host;
22var origin = protocol + sr_origin;
23// Allow absolute or scheme relative URLs to same origin
24return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
25            (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
26// or any other URL that isn't scheme relative or absolute i.e relative.
27            !(/^(\/\/|http:|https:).*/.test(url));
28    }
29function safeMethod(method) {
30return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
31    }
32
33if (!pe) && sameOrigin(settings.url)) {
34        xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
35    }
36 });
简单⽅法
⾸先在你需要发起ajax post请求的页⾯的⾥⾯随便⼀个地⽅加上 {% crsr_token %}
然后浏览器⾥查看源码,会有这么⼀个隐藏标签:<input type="hidden" name="csrfmiddlewaretoken"
value="jlYb5LCP21TxGapw7OuO0xbHmRnyFzlgDapiDl1M1Vp6dOjPM4BlHOgOVeuPYQ27">
在发起ajax post 请求时,组织json参数时,以下⾯这种⽅式使其成为参数,前两个参数是我⾃定义的请⾃⾏忽略,其中键值对中的键名为input标签的name名,值就为其value值
csrf = $('input[name="csrfmiddlewaretoken"]').val();
params = {'sku_id': sku_id, 'count': count, 'csrfmiddlewaretoken': csrf};
这样就可以把csrf中的参数传递给后端,就不会有403错误了,相⽐前⾯⽤了好⼤⼀段JS代码要简洁的多