1.解決したい問題
Django + axiosでPOST通信を行った時、
console.log
Forbidden (CSRF token missing or incorrect.): /top/telling
[10/Nov/2019 11:06:22] "POST /top/telling HTTP/1.1" 403 2556
のように、CSRF起因で403エラー(forbidden)で弾かれてしまう問題を解決します。
2.環境情報
・Django:2.2.6
・axios:0.19.0
・Vue.js:2.6.0
3.対処方法
CookieへCSRFトークンをセットする処理と、
axios利用時にCookieのどの情報をCSRFトークンとして使用するかの設定を行います。
1.CookieへCSRFトークンをセットする
htmlに {% csrf_token %}
を記述し、CookieにCSRFトークンをセットします。
index.html(※一部抜粋)
<html xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="{% static 'css/uikit.min.css' %}"/>
<link rel="stylesheet" type="text/css" href="{% static 'css/main.css' %}"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>
</head>
<body>
<div class="back">
<div class="uk-animation-fade">
<span class="uk-navbar-item title">Destiny - 運命の選択肢 -</span>
<spanf class="uk-navbar-item sub-title">選択に迷ったらぜひご利用ください!幸運を祈ります!<br/></spanf>
<div id="app">
<form action="{% url 'top:index' %}" method="post">
{% csrf_token %}
<div class="uk-text-center">
<button id="btnStart" type="button" v-show="showStart" @click="onStart();"
class="uk-button uk-button-primary">占いを始める
</button>
(以降省略)
2.axios使用時にCookieのどの情報をCSRFトークンとして使用するかを設定する
下記2行をaxiosでのPOST通信時のロジックに追加します。
axios.defaults.xsrfCookieName = 'csrftoken'
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN"
私の場合は下記のように実装しました。
main.js
var app = new Vue({
el : '#app',
data : {
showStart: true,
showSelect: false,
showForm: false,
showResult: false,
choice: 2,
formList: [],
result: ""
},
methods : {
onStart : function() {
this.showStart = false;
this.showSelect = true;
},
onSelect : function(){
this.showSelect = false;
for(var i = 0; i < this.choice; i++) {
this.formList.push({id: i, form:""});
}
this.showForm = true;
},
onExecute : function(){
this.showForm = false;
this.showResult = true;
axios.defaults.xsrfCookieName = 'csrftoken' // ←ココと
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN" // ←ココに追加しました
axios.post('/top/telling',{
formList: this.formList
}).then(function(response) {
this.result = response.data.result;
}.bind(this)).catch(function(error) {
console.log(error);
})
}
}
});
私の場合は上記で解決しました。以上終わり。