MST

星途 面试题库

面试题:Node.js Express应用在微服务架构下的安全性配置与防护

在Node.js Express构建的微服务架构中,服务间通信存在安全风险,例如中间人攻击。阐述如何配置和实现诸如相互TLS认证(mTLS)、JWT令牌用于服务间身份验证以及基于角色的访问控制(RBAC)等安全机制,以保障整个微服务架构的安全性。
46.5万 热度难度
前端开发Node.js

知识考点

AI 面试

面试题答案

一键面试

相互TLS认证(mTLS)

  1. 生成证书
    • 使用OpenSSL等工具生成CA(证书颁发机构)证书、服务端证书和客户端证书。例如,生成CA证书:
    openssl req -x509 -newkey rsa:4096 -days 365 -nodes -out ca.crt -keyout ca.key -subj "/CN=MyCA"
    
    • 生成服务端证书和私钥:
    openssl req -newkey rsa:4096 -days 365 -nodes -out server.csr -keyout server.key -subj "/CN=server.example.com"
    openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
    
    • 生成客户端证书和私钥类似:
    openssl req -newkey rsa:4096 -days 365 -nodes -out client.csr -keyout client.key -subj "/CN=client.example.com"
    openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt
    
  2. 在Express应用中配置
    • 安装https模块(Node.js内置)。
    • 在Express应用中使用以下代码配置mTLS:
    const express = require('express');
    const https = require('https');
    const fs = require('fs');
    
    const app = express();
    const options = {
        key: fs.readFileSync('server.key'),
        cert: fs.readFileSync('server.crt'),
        ca: fs.readFileSync('ca.crt'),
        requestCert: true,
        rejectUnauthorized: true
    };
    
    app.get('/', (req, res) => {
        res.send('Hello, mTLS - protected service!');
    });
    
    https.createServer(options, app).listen(443, () => {
        console.log('Server running on port 443 with mTLS');
    });
    
    • 客户端在发起请求时也需要配置相应的证书:
    const https = require('https');
    const fs = require('fs');
    
    const options = {
        key: fs.readFileSync('client.key'),
        cert: fs.readFileSync('client.crt'),
        ca: fs.readFileSync('ca.crt')
    };
    
    https.get({
        hostname: 'localhost',
        port: 443,
        path: '/',
        method: 'GET',
        rejectUnauthorized: true,
        ...options
    }, (res) => {
        let data = '';
        res.on('data', (chunk) => {
            data += chunk;
        });
        res.on('end', () => {
            console.log(data);
        });
    }).on('error', (e) => {
        console.error(e);
    });
    

JWT令牌用于服务间身份验证

  1. 安装依赖
    • 在Express项目中安装jsonwebtoken
    npm install jsonwebtoken
    
  2. 生成JWT
    • 在服务端,当服务间需要进行身份验证时,生成JWT。例如,在用户登录成功后生成JWT:
    const jwt = require('jsonwebtoken');
    const secret = 'your - secret - key';
    const user = { username: 'testUser', role: 'admin' };
    const token = jwt.sign(user, secret, { expiresIn: '1h' });
    
  3. 验证JWT
    • 在接收请求的服务端,验证JWT。创建一个中间件来验证JWT:
    const jwt = require('jsonwebtoken');
    const secret = 'your - secret - key';
    
    const verifyToken = (req, res, next) => {
        const token = req.headers['authorization'];
        if (!token) {
            return res.status(401).send('Access denied. No token provided.');
        }
        try {
            const decoded = jwt.verify(token.replace('Bearer ', ''), secret);
            req.user = decoded;
            next();
        } catch (error) {
            res.status(400).send('Invalid token.');
        }
    };
    
    app.get('/protected', verifyToken, (req, res) => {
        res.send('This is a protected route.');
    });
    

基于角色的访问控制(RBAC)

  1. 定义角色和权限
    • 在项目中定义不同的角色及其对应的权限。例如:
    const roles = {
        admin: ['create', 'read', 'update', 'delete'],
        user: ['read']
    };
    
  2. 结合JWT实现RBAC
    • 在验证JWT的中间件基础上,添加RBAC逻辑。例如:
    const jwt = require('jsonwebtoken');
    const secret = 'your - secret - key';
    const roles = {
        admin: ['create', 'read', 'update', 'delete'],
        user: ['read']
    };
    
    const verifyToken = (req, res, next) => {
        const token = req.headers['authorization'];
        if (!token) {
            return res.status(401).send('Access denied. No token provided.');
        }
        try {
            const decoded = jwt.verify(token.replace('Bearer ', ''), secret);
            req.user = decoded;
            const requiredPermission = 'create';// 假设这个请求需要创建权限
            if (!roles[decoded.role].includes(requiredPermission)) {
                return res.status(403).send('Forbidden. Insufficient permissions.');
            }
            next();
        } catch (error) {
            res.status(400).send('Invalid token.');
        }
    };
    
    app.get('/create - resource', verifyToken, (req, res) => {
        res.send('Resource created successfully.');
    });