1. 设计通用JWT身份验证中间件
- 安装依赖:在Node.js项目中,首先安装
jsonwebtoken
库,用于生成、验证JWT。
npm install jsonwebtoken
- 创建中间件函数:
const jwt = require('jsonwebtoken');
const { promisify } = require('util');
const verifyJwt = promisify(jwt.verify);
const jwtMiddleware = async (req, res, next) => {
const token = req.headers['authorization'];
if (!token) {
return res.status(401).json({ message: 'No token provided' });
}
try {
const decoded = await verifyJwt(token.replace('Bearer ', ''), process.env.JWT_SECRET);
req.user = decoded;
next();
} catch (error) {
return res.status(401).json({ message: 'Invalid token' });
}
};
module.exports = jwtMiddleware;
- 使用中间件:在各个需要身份验证的路由或服务入口使用该中间件。
const express = require('express');
const app = express();
const jwtMiddleware = require('./jwtMiddleware');
app.get('/protected', jwtMiddleware, (req, res) => {
res.json({ message: 'This is a protected route', user: req.user });
});
2. 保证高并发场景下的性能与安全性
- 性能:
- 缓存:可以使用内存缓存(如
node-cache
)来缓存已验证的JWT,减少重复验证。在中间件中,验证前先检查缓存中是否存在该JWT对应的用户信息。
- 异步处理:使用
async/await
或Promise链式调用,确保验证过程是非阻塞的,提高高并发下的处理能力。
- 安全性:
- 强密钥管理:JWT的密钥
JWT_SECRET
必须足够强壮且保密,定期更换密钥。
- 防止重放攻击:在JWT中加入时间戳或随机数,并在验证时进行检查。例如,在生成JWT时:
const jwt = require('jsonwebtoken');
const currentTime = Math.floor(Date.now() / 1000);
const token = jwt.sign({
sub: user.id,
iat: currentTime,
exp: currentTime + 3600 // 1小时过期
}, process.env.JWT_SECRET);
- **防止中间人攻击**:使用HTTPS协议传输JWT,确保数据在传输过程中的安全性。
3. 处理跨域、跨服务调用问题
- 跨域:
- CORS设置:在Node.js服务中,使用
cors
库来处理跨域问题。安装并配置:
npm install cors
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors({
origin: '*', // 允许所有来源,生产环境应限制
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
}));
- 跨服务调用:
- 传递JWT:在跨服务调用时,将JWT从一个服务传递到另一个服务。例如,使用
axios
进行HTTP调用时:
const axios = require('axios');
const token = req.headers['authorization'];
axios.get('http://another-service.com/protected', {
headers: {
'Authorization': token
}
})
.then(response => {
// 处理响应
})
.catch(error => {
// 处理错误
});
- **服务间信任**:确保各个服务信任彼此传递的JWT,可通过共享密钥或使用公钥/私钥对进行JWT签名验证。例如,使用RSA密钥对:
const jwt = require('jsonwebtoken');
const fs = require('fs');
const privateKey = fs.readFileSync('private.key');
const publicKey = fs.readFileSync('public.key');
// 生成JWT
const token = jwt.sign({ sub: user.id }, privateKey, { algorithm: 'RS256' });
// 验证JWT
const verifyJwt = promisify(jwt.verify);
const decoded = await verifyJwt(token, publicKey, { algorithms: ['RS256'] });