Nodejs POST请求的效率和安全问题请教

Nodejs POST请求的效率和安全问题请教

Node.js 开发指南中4.5介绍HTTP服务器与客户端那一节中提供了一个简单的POST栗子(73页),但作者在页底警告说“这种简单的方法有严重的效率问题和安全问题”。

想请教下,严重的效率问题主要是出在哪一部分,又会产生怎样的安全问题?

谢谢!

var http = require('http');
var querystring = require('querystring');
var util = require('util');
http.createServer(function(req. res){
  var data = '';
  req.on('request', function(chunk){
    post += chunk;
  });
  req.on('end', function(){
    post = querystring.parse(data);
    res.end(util.inspect(post));
  });
}).listen(3000);

顺带请问 这个站怎么会自动退出登录,编辑了好几遍


18 回复

当然可以。以下是对你的问题的回答,包括对效率和安全问题的解释以及改进后的代码示例。

效率问题

  1. 数据累积问题:原始代码中的 data 变量用于存储所有接收到的数据片段。这会导致内存消耗增加,尤其是在处理大量数据时。
  2. 错误处理缺失:没有适当的错误处理机制,如果请求过程中出现任何错误(如网络中断、解析错误等),程序可能无法正确响应。

安全问题

  1. 未验证输入:直接使用 querystring.parse(data) 解析数据,而没有进行任何验证或清理,可能导致注入攻击或其他安全漏洞。
  2. 信息泄露:直接将解析后的数据通过 util.inspect() 输出到响应中,可能会暴露敏感信息。

改进后的代码示例

const http = require('http');
const querystring = require('querystring');

http.createServer((req, res) => {
  if (req.method === 'POST') {
    let body = [];

    req.on('data', (chunk) => {
      body.push(chunk);
    });

    req.on('end', () => {
      try {
        const parsedBody = querystring.parse(Buffer.concat(body).toString());
        
        // 进行必要的数据验证和清理
        // 例如:
        // if (!parsedBody.someField || parsedBody.someField.length > 100) {
        //   res.writeHead(400);
        //   res.end('Bad Request');
        //   return;
        // }

        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify(parsedBody));

      } catch (error) {
        res.writeHead(500);
        res.end('Internal Server Error');
      }
    });
  } else {
    res.writeHead(405);
    res.end('Method Not Allowed');
  }
}).listen(3000);

console.log('Server running at http://localhost:3000/');

解释

  1. 数据累积优化:使用 body 数组来存储数据片段,并在 end 事件触发时将其合并为完整数据。
  2. 错误处理:添加了 try...catch 块来捕获并处理解析过程中的异常。
  3. 数据验证:建议在解析后进行必要的数据验证和清理,以确保数据的安全性。
  4. 响应格式:使用 JSON.stringify() 将数据转换为 JSON 格式输出,而不是使用 util.inspect()

希望这些解释和示例代码对你有所帮助。


楼主可否贴代码

POST 的安全, 应该是 xss 和 csrf 吧

所以以后浏览器要抛弃POST纯用GET?
其实他说的是代码的安全和效率而不是POST。

无代码无真相

已上代码

这个我不懂饿

恩,说的肯定是代码

已上代码

https://github.com/stream-utils/raw-body 楼主可以看看这个模块是怎么来解析 post 的数据的

你的代码…跟POST 一毛钱关系都没啊…

书中给的代码就是如此,如果您有BYVoid编著的Node.js 开发指南,可以翻到第73页看一下。

楼主可以从这个角度想想, 如果request没有把req的end发送过来, 会怎么样呢.

post += chunk; 这里需要限制post的最终大小,要是有人想不停的post,post会吃干净内存。

吃干净内存也不怕 可以通过chunk编码,服务器开始不知道响应字节多少,通过流那样边读边响应 这样既不会当网速慢的时候,储存在内存中爆满,而且也可以加快服务器响应速度

没有安全问题,效率又高的post应该是怎么样的?

7 8 9 楼说得很好。大概也就他们说的那样了。

在这个示例代码中,存在效率和安全问题。我们逐个分析:

效率问题

  1. 内存使用问题

    • data 变量用于存储接收到的数据片段,每次接收新的数据块时都会进行字符串拼接操作。
    • 字符串在 JavaScript 中是不可变对象,这意味着每次拼接都会创建一个新的字符串对象,消耗大量内存和 CPU 资源。
  2. 异步处理不当

    • 事件监听器没有正确地处理错误或超时情况,可能会导致资源泄露或程序阻塞。

安全问题

  1. 未验证输入

    • 代码直接将接收到的数据解析为查询字符串(querystring.parse(data)),这可能导致注入攻击,例如通过发送恶意构造的 POST 数据来执行任意命令。
  2. 缺少安全头信息

    • 没有设置适当的 HTTP 头信息(如 Content-Security-Policy、X-XSS-Protection 等)来增强安全性。

示例代码改进

为了提高效率和安全性,可以对上述代码进行改进:

const http = require('http');
const querystring = require('querystring');

http.createServer((req, res) => {
  if (req.method === 'POST') {
    let body = '';

    // 使用流式读取数据,更高效
    req.on('data', (chunk) => {
      body += chunk.toString(); // 将二进制数据转换为字符串
    });

    req.on('end', () => {
      try {
        const parsedBody = querystring.parse(body);

        // 设置响应头信息,提高安全性
        res.setHeader('Content-Security-Policy', "default-src 'self'");
        res.setHeader('X-XSS-Protection', '1; mode=block');
        
        res.end(JSON.stringify(parsedBody));
      } catch (error) {
        res.writeHead(400, { 'Content-Type': 'text/plain' });
        res.end('Invalid request payload.');
      }
    });
  } else {
    res.writeHead(405, { 'Content-Type': 'text/plain' });
    res.end('Method Not Allowed');
  }
}).listen(3000, () => {
  console.log('Server running at http://localhost:3000/');
});

解释

  • 流式读取:使用 req.on('data', ...) 以流的方式读取数据,避免了重复创建字符串带来的性能问题。
  • 错误处理:添加了 try-catch 块来处理可能的解析错误,并设置了适当的错误响应码。
  • 设置安全头:增加了内容安全策略(CSP)和 XSS 防护头信息,提高了应用的安全性。

通过这些改进,代码不仅在性能上有所提升,而且安全性也得到了加强。

回到顶部