Token+JWT+Redis 實現鑒權機制
使用 Token、JWT 和 Redis 來實現鑒權機制是一種常見的做法,尤其適用于分布式應用或微服務架構。下面是一個大致的實現思路:
1. Token 和 JWT 概述
Token:通常是一個唯一的字符串,可以用來標識用戶的身份。
JWT (JSON Web Token):是一種自包含的、輕量級的認證方式。它由三個部分組成:
Header:包含算法信息(如 HMAC SHA256 或 RSA)和 Token 類型。
Payload:包含聲明信息(如用戶 ID、過期時間等)。
Signature:用于驗證 Token 是否被篡改。
2. Token + JWT + Redis 鑒權機制
這個機制大體分為以下幾個步驟:
步驟 1:用戶登錄并生成 JWT
-
用戶輸入用戶名和密碼進行登錄。
-
服務端驗證用戶信息(用戶名和密碼)是否正確。
-
如果驗證通過,服務端生成 JWT Token:
使用用戶的 ID、角色、權限等信息作為 Payload。設置過期時間(例如 1 小時)作為 Token 的有效期。使用一個密鑰(例如 secretKey)對 Token 進行簽名。
示例 JWT 生成代碼(Node.js + jsonwebtoken 庫):
const jwt = require('jsonwebtoken');const user = { id: 123, username: 'test' }; // 用戶信息
const secretKey = 'your_secret_key'; // 密鑰
const token = jwt.sign(user, secretKey, { expiresIn: '1h' });
服務端將生成的 Token 返回給客戶端,客戶端將 Token 存儲在本地(通常是 localStorage 或 sessionStorage)。
步驟 2:客戶端發送請求時攜帶 JWT
客戶端在每次請求時,將 Token 添加到 HTTP 請求頭中,通常是 Authorization 字段:
Authorization: Bearer <your_jwt_token>
步驟 3:服務端驗證 JWT
每次服務端收到請求時,會驗證請求頭中的 Token 是否有效。
服務端首先檢查 JWT 的簽名和過期時間:
使用密鑰驗證 JWT 的簽名。
如果 JWT 已經過期,拒絕請求,并提示重新登錄。
示例 JWT 驗證代碼:
try {const decoded = jwt.verify(token, secretKey); // 解碼并驗證簽名console.log(decoded); // decoded 包含用戶信息
} catch (error) {// 處理驗證失敗(如過期、無效等情況)res.status(401).send('Unauthorized');
}
除了驗證 JWT 本身,服務端還可以通過 Redis 來檢查 Token 是否在服務端有效。
步驟 4:使用 Redis 存儲和驗證 JWT
Redis 用于存儲和管理 JWT Token,特別是當需要支持 Token 黑名單、Token 強制失效等功能時。
存儲 JWT 到 Redis:
在用戶登錄時,將 JWT 存儲到 Redis,使用用戶 ID 或者 Token 本身作為鍵,設置一個過期時間與 JWT 的有效期一致。
示例代碼(Node.js + ioredis 庫):
const Redis = require('ioredis');
const redis = new Redis();// 假設 JWT 是 token,用戶 ID 是 user.id
redis.set(`token:${user.id}`, token, 'EX', 3600); // 設置過期時間為 1 小時
驗證 Token 是否在 Redis 中:
在每次請求時,服務端可以通過 Redis 查找 Token 是否存在。如果 Token 不存在,說明用戶的 Token 已經失效(比如被登出或超時)。
示例代碼:
const tokenFromRequest = req.headers['authorization'].split(' ')[1]; // 獲取請求中的 Tokenredis.get(`token:${userId}`).then(redisToken => {if (!redisToken || redisToken !== tokenFromRequest) {// Token 不存在或已失效,返回 401return res.status(401).send('Unauthorized');}// Token 驗證通過,繼續處理請求next();
});
步驟 5:登出操作
登出操作:用戶主動登出時,服務端可以將該用戶的 Token 從 Redis 中刪除,確保該 Token 不能再被使用。
示例代碼:
redis.del(`token:${userId}`);
Token 過期:由于 Redis 存儲的 Token 設置了過期時間,當 Token 超過有效期時,Redis 會自動刪除該 Token。
3. 優勢和擴展
Token:能夠輕松支持無狀態的鑒權,不需要在每個請求中攜帶用戶的會話信息。
JWT:自包含的認證信息,不需要在服務器端存儲會話狀態,減少了數據庫壓力。
Redis:用于存儲和管理 Token,提供高效的訪問和強制失效控制。
總結
通過結合 Token、JWT 和 Redis,我們可以實現一個高效且可擴展的鑒權機制,支持無狀態認證、Token 過期控制、強制登出等功能。