VueとRailsで開発していると, axiosでPOSTリクエスト等を送ったときに以下のエラーが出るかと思います。
422 (Unprocessable Entity)
csrfトークン対策しなければならないのですが、エラーを防ぐ方法はいくつかあります。
Railsの場合は、protect_from_forgery
をコメントアウトすれば解決します。
class ApplicationController < ActionController::Base
# protect_from_forgery with: :exception ← コメントアウトする
end
手っ取り早い対処法ですが、CSRF対策を無効にしてしまうため、根本的な解決策になりません。
CSRF対策するためには、ヘッダーにトークンを含める必要があります。
import axios from 'axios'
axios.defaults.headers.common = {
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-TOKEN' : document.querySelector('meta[name="csrf-token"]').getAttribute('content')
};
これでも良いのですが、これを毎回axiosを記述するたびに定義するのは面倒で増えるたびに見通しが悪くなります。
なので、このcsrf-token
が自動でリクエストヘッダーに入るようにしてみました。
##プラグインを作る
適当にplugins
フォルダを作って、以下ののように記述します。
const VueAxiosPlugin = {}
export default VueAxiosPlugin.install = function(Vue, { axios }) {
const csrf_token = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
axios.defaults.headers.common = {
"X-Requested-With": "XMLHttpRequest",
"X-CSRF-Token": csrf_token
}
Vue.axios = axios
Object.defineProperties(Vue.prototype, {
axios: {
get () {
return axios
}
}
})
}
ここでcsrf-token
を設定してます。
後はこのプラグインをエントリーファイルにimport
すれば、
Vue.use
のタイミングでVueAxiosPlugin.install
が呼び出されるようになります。
import Vue from "vue/dist/vue.esm";
import axios from "axios"; // 追加
import VueAxiosPlugin from "./plugins/vue-axios"; // 追加
import App from "./components/App.vue";
Vue.use(VueAxiosPlugin, { axios: axios }) // 追加
new Vue({
el: "#app",
render: h => h(App),
})
Vue.use(VueAxiosPlugin, { axios: axios })
ではimport
してきたaxios
を引数に渡してるのでimport axios from "axios";
を忘れないようにしましょう。
##axios実行ファイル
export default {
methods: {
postComment () {
const params = {
comment: {
email: "テストコメント",
}
}
axios.post("users/sign_in", params)
.then(res => {
console.log(res)
})
}
}
}
Vueインスタンスが作られるタイミングでaxiosが設定されてるため、
いちいちヘッダーにcsrfトークン
を含める必要もありません。
これでだいぶスッキリしましたね。