MST
星途 面试题库

面试题:Node.js HTTPS服务器性能优化及安全加固措施

在Node.js的HTTPS开发中,当服务器面临高并发请求时,可能会出现性能瓶颈。请阐述你所知道的提升HTTPS服务器性能的方法,以及如何进一步加固服务器的安全性,防止常见的网络攻击,如中间人攻击等。
10.6万 热度难度
前端开发Node.js

知识考点

AI 面试

面试题答案

一键面试

提升 HTTPS 服务器性能的方法

  1. 启用 HTTP/2
    • HTTP/2 具有多路复用、头部压缩等特性,相比 HTTP/1.1 能显著提升性能。在 Node.js 中使用 http2 模块来启用 HTTP/2 协议。例如:
    const http2 = require('http2');
    const server = http2.createSecureServer({
      key: fs.readFileSync('path/to/key.pem'),
      cert: fs.readFileSync('path/to/cert.pem')
    });
    server.on('stream', (stream, headers) => {
      stream.respond({
        'content-type': 'text/plain',
        ':status': 200
      });
      stream.end('Hello, World!');
    });
    server.listen(8443);
    
  2. 优化 SSL/TLS 配置
    • 选择合适的加密套件:优先使用现代、安全且高效的加密套件。可以通过 ciphers 选项来配置,如 const options = { key: fs.readFileSync('key.pem'), cert: fs.readFileSync('cert.pem'), ciphers: 'ECDHE - RSA - AES256 - GCM - SHA384:ECDHE - RSA - AES128 - GCM - SHA256' };
    • 启用 TLS 会话复用:通过设置 sessionTicketKey 来启用 TLS 会话复用,减少 TLS 握手开销。例如 const options = { key: fs.readFileSync('key.pem'), cert: fs.readFileSync('cert.pem'), sessionTicketKey: Buffer.from('a 32 - byte key', 'hex') };
  3. 负载均衡
    • 硬件负载均衡器:使用专业的硬件设备(如 F5 Big - IP)来分发流量,它能处理大量并发请求并提供一定的安全防护。
    • 软件负载均衡:如 Nginx 或 HAProxy。在 Node.js 环境中,可以将 Nginx 配置为反向代理服务器,将请求均衡地分发到多个 Node.js HTTPS 服务器实例上。例如 Nginx 配置如下:
    upstream nodejs_servers {
      server 192.168.1.100:8443;
      server 192.168.1.101:8443;
    }
    server {
      listen 443 ssl;
      server_name your_domain.com;
      ssl_certificate /path/to/cert.pem;
      ssl_certificate_key /path/to/key.pem;
      location / {
        proxy_pass https://nodejs_servers;
        proxy_set_header Host $host;
        proxy_set_header X - Real - IP $remote_addr;
        proxy_set_header X - Forwarded - For $proxy_add_x_forwarded_for;
        proxy_set_header X - Forwarded - Proto $scheme;
      }
    }
    
  4. 缓存
    • 静态资源缓存:对于不经常变化的静态资源(如 CSS、JavaScript、图片等),可以设置合适的缓存头。在 Node.js 中,可以使用 http - cache - response 等中间件来实现。例如:
    const express = require('express');
    const app = express();
    const cacheResponse = require('http - cache - response');
    app.get('/static/js/app.js', cacheResponse({
      status: 200,
      headers: {
        'Cache - Control':'public, max - age = 31536000'
      }
    }), (req, res) => {
      res.sendFile(__dirname + '/public/js/app.js');
    });
    
    • 动态内容缓存:对于动态生成但变化不频繁的内容,可以使用内存缓存(如 node - cache)或分布式缓存(如 Redis)。例如使用 node - cache
    const NodeCache = require('node - cache');
    const myCache = new NodeCache();
    app.get('/dynamic - data', async (req, res) => {
      const cachedData = myCache.get('dynamic - data - key');
      if (cachedData) {
        return res.json(cachedData);
      }
      const newData = await fetchDynamicData();
      myCache.set('dynamic - data - key', newData);
      res.json(newData);
    });
    
  5. 优化代码
    • 异步处理:确保所有 I/O 操作(如数据库查询、文件读取等)都是异步的,充分利用 Node.js 的事件驱动和非阻塞 I/O 特性。例如使用 async/await 处理数据库查询:
    const mysql = require('mysql2/promise');
    const connection = await mysql.createConnection({
      host: 'localhost',
      user: 'root',
      password: 'password',
      database: 'test'
    });
    const [rows] = await connection.query('SELECT * FROM users');
    
    • 减少内存占用:避免在请求处理过程中创建大量不必要的对象,及时释放不再使用的资源。例如,在处理完文件读取后,关闭文件描述符:
    const fs = require('fs');
    const readableStream = fs.createReadStream('path/to/file');
    readableStream.on('end', () => {
      readableStream.close();
    });
    

加固服务器安全性,防止常见网络攻击

  1. 防止中间人攻击
    • 证书验证
      • 确保服务器使用的 SSL/TLS 证书是由受信任的证书颁发机构(CA)颁发的。在 Node.js 中,当进行 HTTPS 请求时,默认会验证服务器证书。如果需要自定义证书验证逻辑,可以使用 https.requestrejectUnauthorized 选项。例如:
      const https = require('https');
      const options = {
        hostname: 'example.com',
        port: 443,
        path: '/',
        method: 'GET',
        rejectUnauthorized: true
      };
      const req = https.request(options, (res) => {
        // 处理响应
      });
      req.end();
      
      • 定期更新证书,避免证书过期导致安全风险。
    • 公钥固定(HPKP,HTTP Public Key Pinning):虽然 HPKP 已被弃用,但曾经它可以通过在服务器响应头中添加 Public - Key - Pin 字段,指定服务器预期的公钥哈希,浏览器会验证服务器证书的公钥哈希是否与指定的一致,从而防止中间人替换证书。在 Node.js 中,可以通过设置响应头来实现:
    app.get('*', (req, res) => {
      res.setHeader('Public - Key - Pin','max - age = 604800; pin - sha256 = "base64 - encoded - public - key - hash";');
      res.send('Hello, World!');
    });
    
  2. 防止 DDoS 攻击
    • 限流:使用中间件如 express - rate - limit 来限制单个 IP 地址在一定时间内的请求次数。例如:
    const rateLimit = require('express - rate - limit');
    const limiter = rateLimit({
      windowMs: 15 * 60 * 1000, // 15分钟
      max: 100, // 每个IP在15分钟内最多100个请求
      message: 'Too many requests from this IP, please try again later.'
    });
    app.use(limiter);
    
    • 黑洞路由:与网络服务提供商合作,设置黑洞路由,将大量恶意流量重定向到一个不存在的网络地址,避免服务器受到影响。
  3. 防止 SQL 注入攻击
    • 参数化查询:在进行数据库操作时,使用参数化查询而不是拼接 SQL 字符串。例如在 MySQL 中使用 mysql2 模块:
    const mysql = require('mysql2/promise');
    const connection = await mysql.createConnection({
      host: 'localhost',
      user: 'root',
      password: 'password',
      database: 'test'
    });
    const username = req.body.username;
    const [rows] = await connection.query('SELECT * FROM users WHERE username =?', [username]);
    
  4. 防止 XSS 攻击
    • 输入验证和过滤:对用户输入的数据进行严格的验证和过滤,只允许合法的字符和格式。例如使用 validator 模块验证邮箱地址:
    const validator = require('validator');
    const email = req.body.email;
    if (validator.isEmail(email)) {
      // 处理邮箱
    } else {
      res.status(400).send('Invalid email');
    }
    
    • 输出编码:在将数据输出到页面时,对特殊字符进行编码,防止恶意脚本执行。例如在使用 EJS 模板引擎时,会自动对输出内容进行 HTML 转义:
    <p><%= userInput %></p>
    
  5. 防止 CSRF 攻击
    • 生成和验证 CSRF 令牌:在用户登录后,为每个用户会话生成一个唯一的 CSRF 令牌,并在表单提交或 AJAX 请求时进行验证。例如在 Express 中使用 csurf 中间件:
    const csrf = require('csurf');
    const csrfProtection = csrf({ cookie: true });
    app.get('/form', csrfProtection, (req, res) => {
      res.render('form', { csrfToken: req.csrfToken() });
    });
    app.post('/submit - form', csrfProtection, (req, res) => {
      // 处理表单提交
    });