#使用express-validator在Express中驗證輸入

了解如何驗證Express端點中的輸入數據。

假設你有一個POST端點,接受名字、郵件和年齡參數:

const express = require('express')
const app = express()

app.use(express.json())

app.post('/form', (req, res) => {
 const name = req.body.name
 const email = req.body.email
 const age = req.body.age
})

如何對這些結果進行服務器端驗證,以確保:

  • name是一個至少3個字符的字符串嗎?
  • email是一個真實的郵件地址嗎?
  • age是一個介於0和110之間的數字嗎?

處理Express中從外部輸入的任何類型的驗證的最佳方法是使用express-validator套件

npm install express-validator

您需要從該套件中導入checkvalidationResult對象:

const { check, validationResult } = require('express-validator');

我們將check()調用的數組作為post()調用的第二個參數傳遞。每個check()調用接受參數名作為參數。然後,我們調用validationResult()來驗證是否有驗證錯誤。如果有,我們將錯誤返回給客戶端:

app.post('/form', [
 check('name').isLength({ min: 3 }),
 check('email').isEmail(),
 check('age').isNumeric()
], (req, res) => {
 const errors = validationResult(req)
 if (!errors.isEmpty()) {
 return res.status(422).json({ errors: errors.array() })
 }

 const name = req.body.name
 const email = req.body.email
 const age = req.body.age
})

我使用了以下驗證方法:

  • isLength(),檢查值是否具有指定長度
  • isEmail(),檢查值是否為有效郵件地址
  • isNumeric(),檢查值是否為數字

還有很多其他方法,都來自於validator.js,包括:

  • contains(),檢查值是否包含指定的值
  • equals(),檢查值是否等於指定的值
  • isAlpha(),檢查值是否僅包含字母
  • isAlphanumeric(),檢查值是否僅包含字母和數字
  • isAscii(),檢查值是否僅包含ASCII字符
  • isBase64(),檢查值是否為Base64編碼的字符串
  • isBoolean(),檢查值是否為布爾值
  • isCurrency(),檢查值是否是貨幣格式
  • isDecimal(),檢查值是否為十進制數字
  • isEmpty(),檢查值是否為空
  • isFQDN(),檢查值是否為完全限定域名(Fully Qualified Domain Name)
  • isFloat(),檢查值是否為浮點數
  • isHash(),檢查值是否是哈希值
  • isHexColor(),檢查值是否為十六進制顏色
  • isIP(),檢查值是否為IP地址
  • isIn(),檢查值是否在一個允許的值的數組中
  • isInt(),檢查值是否為整數
  • isJSON(),檢查值是否是有效的JSON字符串
  • isLatLong(),檢查值是否為緯度和經度值
  • isLength(),檢查值是否具有指定的長度
  • isLowercase(),檢查值是否為小寫字母
  • isMobilePhone(),檢查值是否為有效的手機號碼
  • isNumeric(),檢查值是否為數字
  • isPostalCode(),檢查值是否為郵政編碼
  • isURL(),檢查值是否為URL
  • isUppercase(),檢查值是否為大寫字母
  • isWhitelisted(),檢查值是否通過許可字符的白名單

您可以使用matches()方法對輸入進行正則表達式驗證。

日期可以使用以下方法進行檢查:

  • isAfter(),檢查輸入的日期是否在指定日期之後
  • isBefore(),檢查輸入的日期是否在指定日期之前
  • isISO8601(),檢查輸入的日期是否為ISO 8601格式
  • isRFC3339(),檢查輸入的日期是否為RFC3339格式

有關如何使用這些驗證器的詳細信息,請參考 https://github.com/chriso/validator.js#validators

所有這些檢查都可以通過將它們鏈接在一起進行組合:

check('name')
 .isAlpha()
 .isLength({ min: 10 })

如果發生任何錯誤,服務器將自動發送響應以通知錯誤。例如,如果郵件地址無效,將返回以下內容:

{
 "errors": [{
 "location": "body",
 "msg": "Invalid value",
 "param": "email"
 }]
}

對於執行的每個檢查,您可以使用withMessage()方法覆蓋默認錯誤:

check('name')
 .isAlpha()
 .withMessage('必須只包含字母字符')
 .isLength({ min: 10 })
 .withMessage('必須至少10個字符長')

如果您想編寫自己的特殊自定義驗證器該怎麼辦?您可以使用custom驗證器。

在回調函數中,您可以通過拋出異常或返回一個被拒絕的Promise來拒絕驗證:

app.post('/form', [
 check('name').isLength({ min: 3 }),
 check('email').custom(email => {
 if (alreadyHaveEmail(email)) {
 throw new Error('郵件地址已經註冊')
 }
 }),
 check('age').isNumeric()
], (req, res) => {
 const name = req.body.name
 const email = req.body.email
 const age = req.body.age
})

自定義驗證器:

check('email').custom(email => {
 if (已經有這個郵件地址了(email)) {
 throw new Error('郵件地址已經註冊')
 }
})

也可以重寫為:

check('email').custom(email => {
 if (alreadyHaveEmail(email)) {
 return Promise.reject('郵件地址已經註冊')
 }
})