个人github(PS:但愿star):https://github.com/thWinterSun/v-admin前端
最近在用Vue写前端代码,再用vue-resource向后台提交数据。项目后台是用python+Django开发的。下面我就复盘一下我出现问题的通过。vue
首先,想用vue进行数据交互只能引入vue-resource。python
<script src="js/vue.js"></script> <script src="js/vue-resource.js" ></script>
以后我使用vm.$http方法向后台发送数据,其实和jquery的AJAX方法差很少,须要定义发送的地址、请求类型和发送数据等。jquery
this.$http({ url:'/data/', data:JSON.stringify(Strdata), method:'POST' }).then(function(res){ alert(res.data); });
因为POST请求须要修改发送date的Content-Type为application/json,因此要设置emulateJSON为true,就变成这样了git
this.$http({ url:'/data/', data:JSON.stringify(Strdata), method:'POST', emulateJSON:true }).then(function(res){ alert(res.data); });
正常来讲这样就OK了,就能够拿到后台数据了。以后打开控制台,查看network,找到发出的data,看到HTTP状态码为302。github
怎么会被重定向到了登陆页面,难道是登陆超时??ajax
而后我看了看后台服务.....django
不该该是登陆的问题啊,后面有请求成功返回啊,因而我对比了一下成功的请求和失败请求的HTTP请求头,发现好像是少了一个叫X-CSRFToken的东西。这是什么东西呢,因而我就google了一下,获得以下答案:json
Django 提供的 CSRF 防御机制
django 第一次响应来自某个客户端的请求时,会在服务器端随机生成一个 token,把这个 token 放在 cookie 里。而后每次 POST 请求都会带上这个 token,服务器
这样就能避免被 CSRF 攻击。
- 在返回的 HTTP 响应的 cookie 里,django 会为你添加一个 csrftoken 字段,其值为一个自动生成的 token
- 在全部的 POST 表单时,必须包含一个 csrfmiddlewaretoken 字段 (只须要在模板里加一个 tag, django 就会自动帮你生成,见下面)
- 在处理 POST 请求以前,django 会验证这个请求的 cookie 里的 csrftoken 字段的值和提交的表单里的 csrfmiddlewaretoken 字段的值是否同样。若是同样,则代表这是一个合法的请求,不然,这个请求多是来自于别人的 csrf 攻击,返回 403 Forbidden.
- 在全部 ajax POST 请求里,添加一个 X-CSRFTOKEN header,其值为 cookie 里的 csrftoken 的值。
也就是说我每次向后台发送POST请求的时候,Django为了防止跨站请求伪造,即csrf攻击,提供了CsrfViewMiddleware中间件来防护csrf攻击。这时我就知道为何以前将请求方式改成GET后成功了。
以后就想办法在HTTP请求头中设置X-CSRFToken了,我查了不少资料,看到最多的一种方法是这样:
<meta id="token" name="token" value="{ csrf_token() }">
Vue.http.headers.common['X-CSRFToken'] = document.querySelector('#token').getAttribute('value');
可是我试过仍是重定向到登陆页,不知道为何。以后想了想,实际就是获取cookie里面的csrftoken值,而后在赋值给HTTP请求头里面的X-CSRFToken就好了。
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]); if (cookie.substring(0, name.length + 1) == (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } Vue.http.headers.common['X-CSRFToken'] = getCookie('csrftoken');
以后HTTP请求头上的X-CSRFToken就有值了,响应也就成功了。