假設您正在建立一個即將啟動的 Web 應用程式。您精心設計了使用者介面,添加了令人興奮的功能,並確保一切順利運行。但隨著發布日期的臨近,一個揮之不去的問題開始讓你擔心——安全性。具體來說,如何確保只有正確的用戶才能存取應用程式的正確部分。這就是身份驗證的用武之地。
身份驗證是驗證使用者身分的過程,是 Web 開發的關鍵面向。在廣闊的數位環境中,確保用戶可以安全地登入和登出您的應用程式至關重要。一不小心,您的應用程式就可能容易受到攻擊,從而使用戶資料面臨風險。
在本文中,我們將探索 Node.js 中的安全性身份驗證,使用 bcrypt.js 雜湊密碼和 JWT 令牌來管理使用者會話。最後,您將深入了解如何實施強大的登入/登出系統,確保使用者資料的安全。
所以,讓我們踏上建立防彈身份驗證系統的旅程,從設定我們的環境到使用 JWT 保護我們的路由。準備好鎖定您的 Node.js 應用程式了嗎?讓我們開始吧。
首先,使用 npm init -y 初始化 Node.js 項目,這會建立一個具有預設設定的 package.json 檔案。接下來,安裝必要的軟體包:用於設定伺服器的express、用於管理MongoDB的mongoose、用於處理JWT令牌的jsonwebtoken、用於雜湊密碼的bcryptjs、用於環境變數的dotenv、用於啟用跨域資源共享的cors、用於解析cookie的cookie-parser。最後,加入nodemon作為開發依賴,以便在程式碼變更時自動重新啟動伺服器。
1.`npm init -y` 2.`npm install express mongoose jsonwebtoken bcryptjs dotenv cors cookie-parser` 3.`npm install nodemon -D`
現在修改package.json檔案。添加像我的程式碼和類型這樣的腳本。
"scripts": { "dev": "nodemon backend/index.js", "start": "node backend/index.js" }, "type": "module",
接下來,我們將設定一個基本的 Express 伺服器。建立一個名為 index.js 的檔案。此程式碼初始化 Express 並建立應用程式的實例。然後,我們將為根 URL (“/”) 定義一個路由來處理傳入的 HTTP GET 請求。之後,我們將在連接埠 8000 上啟動伺服器,使其能夠偵聽傳入請求。
import express from "express"; const app = express(); app.get("/", (req, res) => { res.send("Server is ready"); }); app.listen(8000, () => { console.log("Server is running on PORT 8000"); });
現在,我們將建立一個名為「routes」的資料夾,並在該資料夾中建立一個名為 authRoute.js 的新文件,並貼上以下程式碼以查看路由的基礎知識。
在此程式碼片段中,我們使用 Express 設定不同驗證端點的路由。首先,我們匯入express庫並建立一個新的路由器實例。然後,我們定義三個 GET 路由:/signup、/login 和 /logout,每個路由都使用一個 JSON 物件回應,指示對應的端點已被命中。最後,我們將路由器實例匯出為預設匯出,使其可用於應用程式的其他部分。
1.`npm init -y` 2.`npm install express mongoose jsonwebtoken bcryptjs dotenv cors cookie-parser` 3.`npm install nodemon -D`
現在更改 index.js 新增驗證路由來測試您的端點。
"scripts": { "dev": "nodemon backend/index.js", "start": "node backend/index.js" }, "type": "module",
現在,您可以在瀏覽器中測試它......但為了方便起見,我將使用 Postman。您可以像這樣測試所有端點。
類似地,您可以看到其他路線,例如註銷和註冊。
所以,我們的基本應用程式已準備就緒......現在使其成為一個強大且正確的身份驗證系統。
現在,首先準備好我們的 mongoDB 資料庫。為此,請建立一個資料夾 Model,並在該資料夾下建立一個檔案 User.js,並在此檔案中為 mongoDB 資料庫中的使用者新增 Mongoose 架構和模型。該架構包括使用者名稱、全名、密碼和電子郵件字段,每個字段都具有指定的資料類型和約束,例如唯一性和所需狀態。密碼欄位的最小長度也為 6 個字元。
import express from "express"; const app = express(); app.get("/", (req, res) => { res.send("Server is ready"); }); app.listen(8000, () => { console.log("Server is running on PORT 8000"); });
現在讓我們連接到我們的資料庫。我們將建立一個名為 db 的資料夾,並在其中建立一個名為 connectDB.js 的檔案。在此檔案中,我們將定義一個非同步函數 connectMongoDB,它嘗試使用 Mongoose 連接到 MongoDB 資料庫。它從 MONGO_URI 環境變數取得資料庫連接字串。如果連線成功,它將記錄一條包含主機名稱的成功訊息。如果失敗,它會記錄錯誤並以狀態代碼 1 退出進程。該函數將被導出以供應用程式的其他部分使用。
import express from "express"; // Create a new Express router instance const router = express.Router(); // Define a GET route for the signup endpoint router.get("/signup", (req, res) => { // Return a JSON response indicating that the signup endpoint was hit res.json({ data: "You hit signup endpoint", }); }); // Define a GET route for the login endpoint router.get("/login", (req, res) => { // Return a JSON response indicating that the login endpoint was hit res.json({ data: "You hit login endpoint", }); }); // Define a GET route for the logout endpoint router.get("/logout", (req, res) => { // Return a JSON response indicating that the logout endpoint was hit res.json({ data: "You hit logout endpoint", }); }); // Export the router instance as the default export export default router;
現在要使用 MONGO_URI,我們必須將其放入 .env 檔案中。這裡我使用了本地 mongoDB 設定連接字串。如果你願意,你也可以使用 mongoDB atlas。
import express from "express"; import authRoute from "./routes/authRoutes.js"; const app = express(); app.get("/", (req, res) => { res.send("Server is ready"); }); app.use("/api/auth", authRoute); app.listen(8000, () => { console.log("Server is running on PORT 8000"); });
現在實作註冊功能。對於這第一個,建立一個資料夾控制器和檔案 authController.js
import mongoose from "mongoose"; // Define the User schema with various fields and their data types const userSchema = new mongoose.Schema( { // The unique username of the user username: { type: String, required: true, unique: true, }, fullName: { type: String, required: true, }, // The password of the user (min length: 6) password: { type: String, required: true, minLength: 6, }, // The email of the user (unique) email: { type: String, required: true, unique: true, }, }, { timestamps: true } ); // Create the User model based on the userSchema const User = mongoose.model("User", userSchema); // Export the User model export default User;
首先,它從請求正文中提取全名、使用者名稱、電子郵件和密碼。它使用正規表示式驗證電子郵件格式,如果格式無效,則傳回 400 狀態。
接下來,函數會檢查使用者名稱或電子郵件是否已存在於資料庫中。如果採取任一操作,則會傳回帶有錯誤訊息的 400 狀態。它還確保密碼長度至少為 6 個字符,如果不滿足此條件,則會發送另一個 400 狀態。
然後使用 bcrypt 對密碼進行安全雜湊處理。使用提供的資料建立一個新的 User 實例並將其儲存到資料庫中。
儲存後,函數會產生一個 JWT 令牌,將其設為 cookie,並傳回 201 狀態以及使用者的 ID、全名、使用者名稱和電子郵件。如果發生任何錯誤,則會將其記錄下來,並發送 500 狀態和「內部伺服器錯誤」訊息。
要啟動此功能,您必須匯入這些
1.`npm init -y` 2.`npm install express mongoose jsonwebtoken bcryptjs dotenv cors cookie-parser` 3.`npm install nodemon -D`
注意到什麼了嗎?一個名為 generateTokenAndSetCookie 的新東西...讓我們看看它的程式碼...建立一個資料夾 utils,其中包含generateTokenAndSetCookie.js。
"scripts": { "dev": "nodemon backend/index.js", "start": "node backend/index.js" }, "type": "module",
**generateTokenAndSetCookie **函數建立一個 JWT 並將其儲存在 cookie 中以用於使用者驗證。
JWT 世代:
函數使用 jsonwebtoken 函式庫建立 JWT。它使用使用者的 ID 和金鑰(來自環境變數的 JWT_SECRET)對令牌進行簽名,並將其設定為在 15 天後過期。
設定 Cookie:
然後該令牌將儲存在使用者瀏覽器上的 cookie 中。 cookie 配置了幾個安全性屬性:
因此此函數可確保使用者工作階段的安全性和持久性,使其成為身分驗證過程的關鍵部分。
這裡我們必須在.env中加入另一個環境變數JWT_SECRET。您可以像這樣添加任何類型的數字和字串混合。
import express from "express"; const app = express(); app.get("/", (req, res) => { res.send("Server is ready"); }); app.listen(8000, () => { console.log("Server is running on PORT 8000"); });
現在我們的註冊功能已經完成..所以現在就開始它的路線。
import express from "express"; // Create a new Express router instance const router = express.Router(); // Define a GET route for the signup endpoint router.get("/signup", (req, res) => { // Return a JSON response indicating that the signup endpoint was hit res.json({ data: "You hit signup endpoint", }); }); // Define a GET route for the login endpoint router.get("/login", (req, res) => { // Return a JSON response indicating that the login endpoint was hit res.json({ data: "You hit login endpoint", }); }); // Define a GET route for the logout endpoint router.get("/logout", (req, res) => { // Return a JSON response indicating that the logout endpoint was hit res.json({ data: "You hit logout endpoint", }); }); // Export the router instance as the default export export default router;
好的,現在讓我們修改我們的index.js,在這裡我們加入了一些新的導入。 dotenv: 從.env 安全地載入環境變數; express.json(): 解析傳入的JSON 請求; express.urlencoded({ Extended: true }): 解析URL 編碼資料; cookieParser: 處理JWT令牌的 cookie; connectMongoDB(): 連接MongoDB進行資料儲存; 路由: /api/auth 管理註冊、登入和登出。
這裡是index.js的更新程式碼
1.`npm init -y` 2.`npm install express mongoose jsonwebtoken bcryptjs dotenv cors cookie-parser` 3.`npm install nodemon -D`
所以。現在是時候在 Postman 中測試我們的註冊功能了。讓我們看看它是否有效。
所以,這是結果。
在這裡你可以看到它運作正常,你也可以檢查你的 mongoDB 資料庫。
現在製作登入功能。讓我們再次回到我們的 authController.js 檔案
"scripts": { "dev": "nodemon backend/index.js", "start": "node backend/index.js" }, "type": "module",
登入控制器透過驗證使用者名稱和密碼來驗證使用者身分。它首先使用用戶名在資料庫中搜尋用戶。如果找到,它會使用 bcrypt 將提供的密碼與儲存在資料庫中的雜湊密碼進行比較。如果使用者名稱或密碼不正確,則傳回錯誤回應。驗證成功後,它會產生一個 JWT 令牌,使用generateTokenAndSetCookie 將其設為 cookie,並傳回成功訊息,表示使用者已成功登入。
讓我們在 authRoutes.js 中加入登入路由
import express from "express"; const app = express(); app.get("/", (req, res) => { res.send("Server is ready"); }); app.listen(8000, () => { console.log("Server is running on PORT 8000"); });
讓我們在 Postman 中測試一下。
這裡可以看到已經成功顯示登入了。
好的。現在是最後一個功能,即註銷功能。讓我們來實現這個。很簡單。
import express from "express"; // Create a new Express router instance const router = express.Router(); // Define a GET route for the signup endpoint router.get("/signup", (req, res) => { // Return a JSON response indicating that the signup endpoint was hit res.json({ data: "You hit signup endpoint", }); }); // Define a GET route for the login endpoint router.get("/login", (req, res) => { // Return a JSON response indicating that the login endpoint was hit res.json({ data: "You hit login endpoint", }); }); // Define a GET route for the logout endpoint router.get("/logout", (req, res) => { // Return a JSON response indicating that the logout endpoint was hit res.json({ data: "You hit logout endpoint", }); }); // Export the router instance as the default export export default router;
註銷控制器透過使用 res.cookie 從客戶端瀏覽器清除 JWT cookie,將其值設為空字串並將 maxAge 設為 0,確保立即過期,從而安全地登出使用者。成功清除 cookie 後,它會發送成功回應,並顯示一則訊息,指示使用者已成功登出。如果在此過程中發生任何錯誤,它會捕獲錯誤、記錄錯誤並傳回內部伺服器錯誤回應。
將此路由加入到我們的 authRoute.js
import express from "express"; import authRoute from "./routes/authRoutes.js"; const app = express(); app.get("/", (req, res) => { res.send("Server is ready"); }); app.use("/api/auth", authRoute); app.listen(8000, () => { console.log("Server is running on PORT 8000"); });
好的。讓我們測試一下我們的最後一個功能,看看它是否正常工作。
哦! …運行得非常好。 ??
所以,現在我們完整的身份驗證後端已準備就緒。 ??
如果您不想自己編寫所有程式碼並想要一個快速解決方案,我建立了一個名為 auth0_package 的 npm 套件。你可以從這裡獲取。
您可以在此處的 github 儲存庫中取得我的上述所有程式碼。
現在您的後端應用程式已完成。在下一篇部落格中,我將解釋如何將其與您的前端整合。所以請繼續關注??.
總之,在 Node.js 應用程式中實現安全身份驗證對於保護用戶資料並確保只有授權用戶才能存取應用程式的特定部分至關重要。透過使用 bcrypt.js 進行密碼雜湊處理並使用 JWT 令牌進行會話管理,您可以建立一個強大的登入/登出系統。這種方法不僅增強了安全性,而且提供了無縫的使用者體驗。設定 MongoDB 資料庫並使用 Express 進行路由進一步增強了後端基礎架構。借助這些工具和技術,您可以放心地啟動您的 Web 應用程序,因為您知道它受到了很好的保護,可以防止未經授權的存取和潛在的安全威脅。
以上是掌握 Node.js 中的安全性驗證:使用 bcrypt.js 和 JWT 登入/登出的詳細內容。更多資訊請關注PHP中文網其他相關文章!