在Nuxt + express設置全域CSRF token

本篇僅適合使用Nuxt+express的使用者。

首先先設置後端,在express官網推薦使用套件csurf,依照套件文件指示,如果要使用cookie認證,還要安裝cookie-parser。

npm install cookie-parser csurf

因為要配合Nuxt後端的銜接程式,所以比較難在單一某個route設置csrf保護,所以就一律設成全域使用,這樣做所有的Post和Put的Route都會檢查csrf token。

var cookieParser = require('cookie-parser')
var csrf = require('csurf')
var express = require('express')

var app = express()

app.use(cookieParser())
app.use(csrf({ cookie: true }))

再來要將每次的網頁請求,要返回的csrf token送給Nuxt,在Nuxt的文件中,只有一個地方可以跟後端的express做銜接,就是在store/index.js,可參考官網網址,這個蠻特別的,包括要從express傳session資料到Nuxt都要用這個。

export const state = () => ({
  csrf_token: ''
})

export const mutations = {
  set_csrf_token (state, val) {
    state.csrf_token = val
  }
}

export const actions = {
  // nuxtServerInit is called by Nuxt.js before server-rendering every page
  nuxtServerInit ({ commit }, { req }) {
    //set csrf
    commit('set_csrf_token', req.csrfToken())
  }
}

這樣做就能保證每次要求網頁,都能將伺服端產生的csrf token保存在Nuxt的store裡面了。

接著我們要設定Nuxt的axios模組,讓它每次在傳送資料到後端的時候,能自帶header參數。因為根據剛csruf的設定,每次的post都會檢查header是否有 ‘CSRF-Token’ 的參數,並檢查token是否正確。

首先先設定nuxt.config.js

plugins: [
  '~/plugins/axios'
],

在plugins資料夾新增一個axios.js的檔案,內容如下

export default function ({ $axios, app, store }) {
   $axios.onRequest(config => {
     config.headers.common['CSRF-Token'] = store.state.csrf_token
   })
 }

如此一來每次在做post的時候,應該就能自帶一個’CSRF-Token’的參數在header裡面了。測試看看吧。

let res = await this.$axios.$post('/test/csrf/',  { name: 'John' })
console.log(res)

大功告成。

Leave a Reply

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *