如何在Node+React項目中防止CSRF攻擊

什麼是CSRF攻擊

CSRF(Corss-site request forgery)即跨站請求僞造攻擊,也常縮寫爲XSRF,是一種常見的web攻擊方式。前端

簡單來講,CSRF攻擊就是:用戶訪問正常網站A的時候,會在瀏覽器中留下一些登陸信息(好比cookie),惡意網站B利用這些登陸信息,僞造一些請求信息,告訴正常網站A我使合法用戶,從而對網站A進行攻擊。ios

下面經過一張圖來闡述該攻擊的過程和原理:web

如何防護CSRF攻擊

在項目中防護CSRF攻擊的時候,能夠遵循如下幾個方面:shell

  • Get請求不對網站中的數據進行修改
  • 設置cookie的安全數據,不讓第三方網站訪問到用戶的cookie
  • 組織第三方網站請求接口
  • 服務端接收到請求時,校驗驗證信息,好比驗證碼或者token

下面咱們已Node + React項目爲例,來闡述如何經過校驗token來方式CSRF攻擊。這裏咱們使用到一個很成熟的第三方包:csurfnpm

須要說明的是,這個示例中後端使用cookie來輔助管理token信息,因此項目中已經使用了 cookie-parser ,更詳細的信息能夠參考 csurf 官當文檔axios

從開發角度來講,能夠分爲三個步驟:後端

  1. 後端API生成token
  2. 前端發送請求,獲取token並存儲到本地,在後續的請求中講token附帶到請求頭中
  3. 後端接收到請求,校驗請求頭中的token是否合法,若是合法則繼續執行,不然直接返回相關報錯信息給前端。

在後端API中生成token並返回給前端請求

首先執行一下腳本,講csurf包安裝到項目中:瀏覽器

npm install csurf
複製代碼

而後在項目中引入該包,寫一個生成token的API,代碼示例以下:安全

var csrf = require('csurf')

var csrfProtection = csrf({ cookie: true });
app.get(`/getCsrfToken`, csrfProtection, (req, res) => {
    res.send({ csrfToken: req.csrfToken() });
})
複製代碼

前端獲取token並添加到後續請求頭中

在使用React開發的前端項目中,能夠在根組件掛載完成以後,在其餘全部請求以前,調用 /getCsrfToken 請求,獲取token。這裏建議在根組件的 componentDidMount 生命週期中發起請求,而後將獲得的token保存到sessionStorage中。示例代碼以下:markdown

import axios from 'axios';

componentDidMount() {
    axios.get('/getCsrfToken')
        .then(res => {
            if (res && res.data && res.data.csrfToken) {
                window.sessionStorage.setItem('CSRF-Token', res.data.csrfToken);
            } else {
                throw new Error("Get CSRF token failed");
            }
        }).catch(() => {
            throw new Error("Get CSRF token failed");
        });
}
複製代碼

獲取token以後,在其餘的API請求中,都將該token設置到請求頭中,一塊兒發送到後端API中。這裏以 axios 爲例,展現如何設置請求頭:

import axios from 'axios';

// 在建立axios實例的時候,設置請求頭信息
this.axios = axios.create({
    headers: {
        'CSRF-Token': window.sessionStorage.getItem('CSRF-Token') || ""
    }
})

// 修改已建立的axios實例的請求頭信息
this.axios.defaults.headers.common['CSRF-Token'] =  window.sessionStorage.getItem('CSRF-Token');
複製代碼

如此一來,前端在發送請求的時候,就會將token信息附在請求頭中,一塊兒發給後端進行處理。

在後端校驗token信息的合法性

在前面生成token信息的時候,咱們已經經過如下代碼建立了一個csurf實例:

var csrfProtection = csrf({ cookie: true });
複製代碼

咱們能夠直接以中間件的形式使用該實例對token進行校驗,即:

app.use(csrfProtection);
複製代碼

到這裏,一個基本的防護CSRF攻擊的措施就完成了,須要注意的是,使用csurf包進行防護CSRF攻擊的時候,會校驗兩個變量:一個是自動添加到cookie中的_csrf,一個就是上述生成的token,兩者缺一不可。

寫在後面

博客中若有錯誤之處,還但願各位達大佬予以糾正。

相關文章
相關標籤/搜索