JavaScript >> Javascript 文檔 >  >> Node.js

使用 express-validator 在 Node.js 中進行表單數據驗證

簡介

在構建應用程序(尤其是面向客戶端的應用程序)時,必須執行服務器端驗證。原因是,永遠不能只依賴用戶的輸入;因為這些輸入有時包含虛假/惡意數據。

客戶端驗證是篩選大部分輸入的好方法,但您仍然需要執行服務器端驗證。

在 Node.js 中驗證數據的方法有很多種,在本文中,我們將介紹 express-validator。 Express-validator 是一個包含 validator.js 的庫 並將其功能公開為一組中間件。

項目設置

對於本教程,我們將構建一個演示後端服務器來模擬用戶註冊和使用 Node.js 登錄。這些字段將強制執行某些規則,我們將驗證通過的數據。

首先,我們將創建一個項目文件夾,導航到它並初始化它:

# Create the project folder
$ mkdir express-validator-tut

# Navigate into the project folder
$ cd express-validator-tut

# Initialize project
$ yarn init -y
# OR
$ npm init -y

完成後,我們將通過運行以下命令安裝以下依賴項:

$ yarn add body-parser express express-validator
# OR
$ npm i body-parser express express-validator

我們來看看我們安裝了什麼:

  • 快遞: Node.js 的輕量級 Web 應用程序框架。我們將使用它來處理後端服務器中的路由。
  • 正文解析器: 一個中間件,它將幫助我們將傳入的請求輸入(用戶輸入)解析到 req.body 對象。
  • 快速驗證器: 我們將用於處理傳入輸入驗證的庫。

最後,我們將創建一個 index.js 在我們的項目目錄中存放用於實例化 Express 應用程序/服務器的樣板代碼的文件:

// index.js
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const port = 2022;

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.post('/register', (req, res) => {});
    
app.listen(port);
console.log('See where it all happens at http://localhost:'+port);

現在,讓我們用 node 運行這個應用程序 :

$ node index.js 

如果一切順利,您的終端應該會輸出如下內容:

使用 express-validator 的標準驗證規則

在本節中,我們將學習如何向傳入請求添加簡單的驗證和清理規則。首先,我們要檢查輸入到電子郵件字段中的值是否是有效的電子郵件。然後,我們要強制密碼至少包含 6 個字符。

首先,讓我們在 /login 中添加幾個中間件函數 路線:

// index.js
...
const { body, validationResult } = require('express-validator');

app.post('/login',
    body('email').isEmail().normalizeEmail(),
    body('password').isLength({
        min: 6
    }),
    (req, res) => {
        const errors = validationResult(req);

        if (!errors.isEmpty()) {
            return res.status(400).json({
                success: false,
                errors: errors.array()
            });
        }

        res.status(200).json({
            success: true,
            message: 'Login successful',
        })
    });
...

在上面的代碼片段中,我們使用了兩個驗證器方法:

  • isEmail() :此驗證器函數檢查傳入的字符串是否為有效的電子郵件地址。
  • isLength() :此驗證器檢查字符串的長度是否在指定範圍內。在我們的例子中,指定的範圍至少為 6 個字符。

我們可以使用的其他一些方法是:

  • isNumeric() - 檢查輸入是否為數字
  • contains() - 檢查輸入是否包含某個值
  • isBoolean() - 檢查輸入是否為布爾值
  • isCurrency() - 檢查輸入是否為貨幣格式
  • isJSON() - 檢查輸入是否為 JSON
  • isMobilePhone() - 檢查輸入的手機號碼是否有效
  • isPostalCode() - 檢查輸入是否是有效的郵政編碼
  • isBefore()isAfter() - 檢查日期是在另一個日期之前還是之後

還有其他的,但這些可能可以滿足您的大部分驗證需求。

為確保用戶提供的電子郵件地址沒有噪音和違規行為,我們將在我們的電子郵件字段中添加消毒劑,如上面的片段所示。 normalizeEmail() 方法有助於將輸入的電子郵件轉換為標準批准的格式。這意味著如果用戶輸入,例如,[email protected] ,它將被規範化為 [email protected] .

Validator.js 提供了一些靈活性,因為此選項可以切換 offon 但設置為 on 默認。如果您計劃對輸入進行規範化,您可能需要查看許多規範化選項。如果您想了解更多關於其他驗證器/清理器功能的信息,可以查看 Validator.js 的官方文檔。

讓我們通過發送一個包含無效密碼和 @googleemail.com 的請求來測試我們的代碼 電子郵件,使用 Postman 或 curl

免費電子書:Git Essentials

查看我們的 Git 學習實踐指南,其中包含最佳實踐、行業認可的標準以及隨附的備忘單。停止谷歌搜索 Git 命令並真正學習 它!

到目前為止,我們已經了解瞭如何驗證示例登錄端點的傳入輸入。現在讓我們切換到註冊端點,涵蓋自定義驗證規則、錯誤消息、模式驗證和驗證消息標準化等任務。

使用 express-validator 自定義驗證規則和錯誤消息

首先,讓我們通過將以下代碼段添加到我們的 index.js 來創建我們的用戶註冊端點 文件:

// index.js
...
app.post('/register', (req, res) => {
    // Validate incoming input
    res.status(200).json({
        success: true,
        message: 'Registration successful',
    });
});
...

custom() 方法

為了確保我們的用戶在註冊過程中輸入唯一的用戶名,我們不能使用從 Validator.js 方法包裝的標準方法,因為沒有方法可以檢查它。

我們必須為此編寫一個自定義驗證器,這可以使用 custom() 來完成 方法。 custom() 方法接受一個函數,該函數也可以是異步的。如果函數是異步的,你會想要在驗證失敗時拒絕承諾,並指定自定義消息。如果沒有,你可以拋出異常。

讓我們先從拒絕一個承諾開始:

// index.js
...
app.post('/register',
    body("username").custom(value => {
        return User.find({
            username: value
        }).then(user => {
            if (user.length > 0) {
                // Custom error message and reject
                // the promise
                return Promise.reject('Username already in use');
            }
        });
    }),
    (req, res) => {
        // Validate incoming input
        const errors = validationResult(req);
        if (!errors.isEmpty()) {
            return res.status(400).json({
                errors: errors.array()
            });
        }
        ...
    })

在上面的代碼片段中,我們調用了 find() User 模型 Mongoose 模式上的方法來檢查客戶端輸入的用戶名是否已經存在於我們的數據庫中。

如果它存在,我們會拒絕承諾並返回一條我們想要返回給用戶的消息。

儘管在指定數據庫模式時,如果用戶名字段被標記為唯一,MongoDB 會自動檢測到這一點。建議在它到達數據庫之前處理它,這樣我們的應用程序就不會過早崩潰。

或者,您可以拋出異常來表示無效輸入:

// index.js
...
    
app.post('/register',
        body("username").custom(value => {
            return User.find({
                username: value
            }).then(user => {
                if (user.length > 0) {
                    throw ("Username is taken!"); //custom error message
                }
            });
        }),
...

withMessage() 方法

實現自定義驗證錯誤消息的第二種方法是使用 withMessage() 鏈。可以放多個驗證器,後面跟 withMessage() 為每個驗證指定錯誤消息的鍊式方法:

body("parameter")
    .validator1()
    .withMessage('Message 1')
    .validator2()
    .withMessage('Message 2')

讓我們將其與實際方法一起應用到我們的示例中:

// index.js
    
...
app.post('/register',
    body("password").isStrongPassword({
        minLength: 8,
        minLowercase: 1,
        minUppercase: 1,
        minNumbers: 1
    })
    .withMessage("Password must be greater than 8 and contain at least one uppercase letter, one lowercase letter, and one number"),
    (req, res) => {
        // Validate incoming input
    })
...

讓我們用一個無效的密碼和一個已經在使用的用戶名發出另一個請求:

使用 express-validator 進行架構驗證

模式驗證提供了一種更簡潔的數據驗證方法。我們不是調用大量函數,而是為每個字段指定驗證規則,並將模式傳遞給一個名為 checkSchema() 的中間件函數 .

在下面的代碼片段中,我們將為用戶註冊端點創建一個驗證模式:

// index.js
... 
const {body, checkSchema, validationResult} = require('express-validator');
const registrationSchema = {
    username: {
        custom: {
            options: value => {
                return User.find({
                    username: value
                }).then(user => {
                    if (user.length > 0) {
                        return Promise.reject('Username already in use')
                    }
                })
            }
        }
    },
    gender: {
        notEmpty: true,
        errorMessage: "Gender field cannot be empty"
    },
    password: {
        isStrongPassword: {
            minLength: 8,
            minLowercase: 1,
            minUppercase: 1,
            minNumbers: 1
        },
        errorMessage: "Password must be greater than 8 and contain at least one uppercase letter, one lowercase letter, and one number",
    },
    phone: {
        notEmpty: true,
        errorMessage: "Phone number cannot be empty"
    },
    email: {
        normalizeEmail: true,
        custom: {
            options: value => {
                return User.find({
                    email: value
                }).then(user => {
                    if (user.length > 0) {
                        return Promise.reject('Email address already taken')
                    }
                })
            }
        }
    }
}
...

通過指定一個模式,我們可以深入到特定的輸入字段以應用驗證器和清理器,它比我們在前面幾節中看到的將許多方法與驗證消息鏈接起來更具可讀性。

現在,我們可以繼續使用這個 checkSchema() 驗證註冊數據:

app.post('/signup', checkSchema(registrationSchema), (req, res) => {
    // Validate incoming input
    const errors = validationResult(req);

    if (!errors.isEmpty()) {
        return res.status(400).json({
            errors: errors.array()
        });
    }

    res.status(200).json({
        success: true,
        message: 'Registration successful',
    });
})

如果您只需要少量驗證並希望保持簡單,則可以使用方法。如果你有大量的驗證需要做,那麼如果你使用模式驗證,它的可讀性會更好。

使用 express-validator 標準化驗證響應

express-validator 使得標準化驗證錯誤響應成為可能。這意味著您可以創建中間件函數來運行驗證和處理驗證錯誤。

如何做到這一點的一個例子是創建一個 validate() 函數將接受我們所有的驗證器並使用 Promise.all() 並行運行它們 :

// index.js
const validate = validations => {
    return async (req, res, next) => {
        await Promise.all(validations.map(validation => validation.run(req)));

        const errors = validationResult(req);
        if (errors.isEmpty()) {
            return next();
        }

        res.status(400).json({
            errors: errors.array()
        });
    };
};

現在我們的 validate 函數已經創建,我們可以在多個路由上重複使用它。讓我們將它應用到我們的登錄和註冊路由中:

// index.js
...
app.post('/login', validate([
        body('email').isEmail().normalizeEmail(),
        body('password').isLength({
            min: 12
        })
    ]),
    (req, res) => {
        // Process data
        res.status(200).json({
            success: true,
            message: 'Login successful',
        })
    });

app.post('/register', validate(checkSchema(registrationSchema)), (req, res) => {
    // Process data
    res.status(200).json({
        success: true,
        message: 'Registration successful',
    });
});
...

如上面的代碼片段所示 - 使用自定義驗證中間件運行我們所有的驗證器和消毒器,不僅通過 Promise.all() 提高了我們的性能 調用,但我們也可以提高代碼的可讀性。當我們需要驗證大量表單字段時,這將證明是有用的。

結論

在本文中,我們介紹了 express-validator 的基本和更高級的用法 ,一個很棒的輕量級庫,它圍繞著著名的 validator.js 圖書館。


Tutorial JavaScript 教程
  1. 從具有超過 10,000 個鍵/值對的對像中查找值的有效方法

  2. 使用 Vue 3 註冊全局組件

  3. 禁止使用 Firefox 加載特定的 JavaScript 文件

  4. 在 Netlify 上使用路由器部署 React 應用程序

  5. 如何從 JavaScript 中的 URL 獲取查詢參數

  6. 公證您的 Electron 應用程序

  7. Vue 2.x 的簡單 localStorage 綁定

  1. 依賴注入實用介紹

  2. 如何在 JavaScript 中使用過濾器動態過濾數組

  3. React 軍械庫中的必備武器

  4. RxJS 提示:創建函數:of()

  5. NestJS:控制器

  6. 2019 年市場上可供初級 JavaScript 開發人員使用的十大 Github 應用

  7. 很棒的 Vue.js 資源

  1. 將您的第一個 ReactJS 應用程序部署到雲中

  2. Ansible 入門教程 - 自動化您的基礎架構

  3. 如何根據 JavaScript 中的自定義數字更改輸入值?

  4. 使用 Tracking.js 在 JavaScript 中進行面部檢測