Node登陸認證實戰(zhàn)!十分鐘手把手教會你!
圖片
零.前言
在企業(yè)級開發(fā)中,Token 認證機制已成為保護 API 安全的行業(yè)標準。
本文將演示如何通過 Node.js 生成 JSON Web Token (JWT),并結合 Redis 緩存實現(xiàn)完整的認證流程。
一.安裝工具庫
- express:Express 的作用相當于 node.js 的內置模塊 http,是專門用來創(chuàng)建web服務器的。用來接收前端的請求。
- jsonwebtoken:生成、校驗 token 的工具。
- ioredis:緩存數(shù)據的工具,對 redis 插件進行封裝,集成 promise 等工具。
- dotenv:用來管理本地環(huán)境變量。
- mysql2:操作數(shù)據庫
- sequelize:封裝數(shù)據庫操作,通過內置 api 而不是sql語句操作數(shù)據庫。
npm install express jsonwebtoken ioredis dotenv mysql2 sequelize
二.配置環(huán)境
在項目根目錄新建 .env 文件
圖片
在 app.js 中配置 dotenv
圖片
require('dotenv').config();
然后我們就可以在項目中自定義的文件中獲取 .env 文件中配置的數(shù)據了,例如:
process.env.REDIS_PORT
三.配置 Redis
圖片
Redis 是一個高性能的鍵值存儲數(shù)據庫,常用于緩存、消息隊列、會話存儲等場景。
在 Node.js 中使用 Redis 可以顯著提升應用性能,尤其是在頻繁讀取數(shù)據的場景下。
如果你是前端小白,這里你就把 Redis 當成一個很牛逼的數(shù)據庫,可以存各式各樣的數(shù)據,可以給存儲的數(shù)據設置過期時間,時間一到就自動刪除了。
Redis 和 MySQL 數(shù)據庫一樣,分為服務端和客戶端。服務端用來存儲數(shù)據,客戶端用來對數(shù)據進行讀寫操作。
所以我們要先安裝服務端,再安裝客戶端。
安裝 Redis 服務端的文章大家可以自行搜索,或者去問 DeepSeek、豆包等大模型,這里不再贅述。
圖片
而本文我們安裝的 ioredis 是一個 Node.js 環(huán)境下的 Redis 客戶端庫。我們可以通過它內置的 API 操作 Redis 數(shù)據庫中的數(shù)據。
3.1 配置 Redis
新建 config 文件夾,然后新建 redis.js 文件:
圖片
將創(chuàng)建好的 Redis 配置文件加載到 app.js 中
四.jwt 生成 token
古代調兵遣將需要兵符,這個兵符就是個憑證,憑證為真,兵部才允許你把兵調走。
同樣在系統(tǒng)開發(fā)中,只有是這個系統(tǒng)的用戶才被允許訪問一些資源。
1.前端用戶登陸成功之后,后臺通過一個工具將一段字符串返回給前端用戶。
2.前端用戶每次訪問其他頁面(資源)的時候請求頭都攜帶這個字符串。
3.后端拿到這個字符串之后再用工具去校驗,校驗通過,就允許訪問其他資源。
所以我們說的字符串就是 token,只不過這個字符串比較復雜。
而JWT是一種具體的 Token 實現(xiàn)方式,是一種認證解決方案。
你可以把 token 看做是 JWT。
而項目中我們安裝的 jsonwebtoken 是一個生成 token 字符串、校驗 token 的工具。比如它的生成 token 的方法:
jwt.sign(
user,// Payload
JWT_SECRET, // 秘鑰
{ expiresIn: 3600000 } // 令牌過期時間(1小時)
);
所以 JWT 由三部分組成,用點號(.)分隔:
- Header(頭部):包含令牌的類型和簽名算法。
- Payload(載荷):包含聲明(Claims),即關于用戶或其他實體的信息。
- Signature(簽名):用于驗證令牌的完整性和真實性。 一個典型的 JWT 看起來像這樣:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaGFuIEdvZGxleSIsImlhdCI6MTUxNjIzOTAzMCwiZXhwIjoxNTE2MjM5MDkwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
也就是使用 jsonwebtoken 庫的 sign 方法就能生成一個 token 字符串。
前面說了一堆廢話,接下來配置 jwt 工具:在 utils 文件夾在新建 jwt.js 文件
圖片
在 app.js 文件中加載 jwt。
圖片
注:jsonwebtoken 設置 token 過期時間有兩種方式:
1.數(shù)值,1h=60*60*1000=3600000
const token = jwt.sign(
{ id: user.id, },// Payload
process.env.JWT_SECRET, // 秘鑰
{ expiresIn: 3600000 }
);
2.字符串: 1h表示1小時,2m表示2分鐘,24d表示24天
const token = jwt.sign(
{ id: user.id, },// Payload
process.env.JWT_SECRET, // 秘鑰
{ expiresIn: "1h" }
);
五.改造用戶登陸接口
核心流程:
1.獲取請求參數(shù):username 和 password
2.使用 sequelize 的 findOne 方法查詢用戶信息。注:sequelize 工具的使用在前面幾篇文章講的有,這里不再贅述。
3.如果用戶不存在,返回錯誤信息。
4.用戶存在,密碼不對,返回錯誤信息
5.生成 token 信息
6.將token信息存儲到 redis,設置過期時間
7.將token返回給前端
// 用戶登陸
router.post('/login', async (req, res) => {
try {
const { username, password } = req.body;
// 根據用戶名查詢用戶信息
constuser = awaitUser.findOne({
where: {
username: username,
}
});
// 用戶存在
if (user) {
// 校驗密碼
if (password != user.password) {
throw new CustomError("密碼錯誤!");
}
// 生成token
consttoken = generateToken(user);
// 將token存儲到Redis
awaitredisClient.set(`token:${user.id}`, token, 'EX', 3600); // 1小時過期
// 將token返回
constresult = { token: token };
success(res, "登錄成功", result);
} else {
throw new CustomError("用戶不存在!");
}
} catch (err) {
res.status(500).json({ error: err.message });
}
});
注:redis 存儲數(shù)據的方法:
- 參數(shù)1:key
- 參數(shù)2:value
- 參數(shù)3:固定,表示設置過期時間
- 參數(shù)4:過期時間具體值,3600表示 1 小時,和jwt不一樣。
redisClient.set(key, value, 'EX', 過期時間)
測試結果:
密碼錯誤;
圖片
登陸成功,返回 token 信息。
六.Token 身份校驗
在 utils 文件夾下新建 auth.js 文件:
圖片
核心流程:
1.從請求頭中獲取 token 信息,如果 token 不存在,就返回錯誤信息
2.使用 jsonwebtoken 庫的 verify 方法校驗 token 信息,校驗失敗返回錯誤信息
3.從Redis緩存中獲取 token 信息,如果 token 不存在,就返回錯誤信息
4.校驗成功,才能訪問其他資源
圖片
然后在需要進行安全校驗的接口上面添加這個方法:
圖片
測試:
1.header 為空
圖片
2.token校驗失敗
圖片
3.token校驗成功
圖片
七.完整代碼
通過網盤分享的文件:zhifou-mall-node-api.zip
鏈接: https://pan.baidu.com/s/10zOgKQiNfBIrppfAUk6lpw?pwd=6666
提取碼: 6666
拿到代碼之后記得:
- npm install 安裝依賴
- 修改 Sequelize.js 里面連接 MySQL 數(shù)據庫的賬號密碼等配置項
- 修改 .env 文件 redis 的配置信息
- npm app.js 啟動后端項目