pos提交提交数据时碰到Django csrf

  个人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 攻击。

  1. 在返回的 HTTP 响应的 cookie 里,django 会为你添加一个 csrftoken 字段,其值为一个自动生成的 token
  2. 在全部的 POST 表单时,必须包含一个 csrfmiddlewaretoken 字段 (只须要在模板里加一个 tag, django 就会自动帮你生成,见下面)
  3. 在处理 POST 请求以前,django 会验证这个请求的 cookie 里的 csrftoken 字段的值和提交的表单里的 csrfmiddlewaretoken 字段的值是否同样。若是同样,则代表这是一个合法的请求,不然,这个请求多是来自于别人的 csrf 攻击,返回 403 Forbidden.
  4. 在全部 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就有值了,响应也就成功了。

 

相关文章
相关标签/搜索