MST

星途 面试题库

面试题:Node.js JWT与分布式系统中的身份验证整合

在一个基于Node.js的微服务分布式系统中,各个服务之间通过JWT进行身份验证。请详细描述如何设计一个通用的JWT身份验证中间件,使其能够在不同服务间无缝共享用户身份信息,同时保证在高并发场景下的性能与安全性,以及如何处理JWT在跨域、跨服务调用时可能出现的问题。
47.0万 热度难度
前端开发Node.js

知识考点

AI 面试

面试题答案

一键面试

1. 设计通用JWT身份验证中间件

  1. 安装依赖:在Node.js项目中,首先安装jsonwebtoken库,用于生成、验证JWT。
npm install jsonwebtoken
  1. 创建中间件函数
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;
  1. 使用中间件:在各个需要身份验证的路由或服务入口使用该中间件。
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. 保证高并发场景下的性能与安全性

  1. 性能
    • 缓存:可以使用内存缓存(如node-cache)来缓存已验证的JWT,减少重复验证。在中间件中,验证前先检查缓存中是否存在该JWT对应的用户信息。
    • 异步处理:使用async/await或Promise链式调用,确保验证过程是非阻塞的,提高高并发下的处理能力。
  2. 安全性
    • 强密钥管理: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. 处理跨域、跨服务调用问题

  1. 跨域
    • 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']
}));
  1. 跨服务调用
    • 传递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'] });