71
63

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Vue】axiosで、デフォルトでCSRFトークンを設定できるようにする

Last updated at Posted at 2019-07-31

VueとRailsで開発していると, axiosでPOSTリクエスト等を送ったときに以下のエラーが出るかと思います。

422 (Unprocessable Entity)

csrfトークン対策しなければならないのですが、エラーを防ぐ方法はいくつかあります。

Railsの場合は、protect_from_forgeryをコメントアウトすれば解決します。

app/controllers/application_controller.rb
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フォルダを作って、以下ののように記述します。

app/javascript/packs/plugins/vue-axios.js
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が呼び出されるようになります。

index.js

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トークンを含める必要もありません。

これでだいぶスッキリしましたね。

参考: https://tech.medpeer.co.jp/entry/2018/02/26/080000

71
63
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
71
63

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?