個人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就有值了,響應也就成功了。