防止跨站請求偽造(CSRF)

CSRF 是一種攻擊,它迫使終端使用者在他/她當前經過身份驗證的 Web 應用程式上執行不需要的操作。

之所以會發生這種情況,是因為每次向網站發出請求都會傳送 cookie - 即使這些請求來自不同的網站。

我們可以使用 csurf 模組建立 csrf 令牌並驗證它。

var express = require('express')
var cookieParser = require('cookie-parser')    //for cookie parsing
var csrf = require('csurf')    //csrf module
var bodyParser = require('body-parser')    //for body parsing

// setup route middlewares
var csrfProtection = csrf({ cookie: true })
var parseForm = bodyParser.urlencoded({ extended: false })

// create express app
var app = express()

// parse cookies
app.use(cookieParser())

app.get('/form', csrfProtection, function(req, res) {
  // generate and pass the csrfToken to the view
  res.render('send', { csrfToken: req.csrfToken() })
})

app.post('/process', parseForm, csrfProtection, function(req, res) {
  res.send('data is being processed')
})

因此,當我們訪問 GET /form 時,它會將 csrf 標記 csrfToken 傳遞給檢視。

現在,在檢視內部,將 csrfToken 值設定為名為 _csrf 的隱藏輸入欄位的值。

例如,對於 handlebar 模板

<form action="/process" method="POST">
    <input type="hidden" name="_csrf" value="{{csrfToken}}">
    Name: <input type="text" name="name">
    <button type="submit">Submit</button>
</form>

例如,對於 jade 模板

form(action="/process" method="post")
    input(type="hidden", name="_csrf", value=csrfToken)

    span Name:
    input(type="text", name="name", required=true)
    br

    input(type="submit")

例如,對於 ejs 模板

<form action="/process" method="POST">
    <input type="hidden" name="_csrf" value="<%= csrfToken %>">
    Name: <input type="text" name="name">
    <button type="submit">Submit</button>
</form>