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);
顺带请问 这个站怎么会自动退出登录,编辑了好几遍
当然可以。以下是对你的问题的回答,包括对效率和安全问题的解释以及改进后的代码示例。
效率问题
- 数据累积问题:原始代码中的
data
变量用于存储所有接收到的数据片段。这会导致内存消耗增加,尤其是在处理大量数据时。 - 错误处理缺失:没有适当的错误处理机制,如果请求过程中出现任何错误(如网络中断、解析错误等),程序可能无法正确响应。
安全问题
- 未验证输入:直接使用
querystring.parse(data)
解析数据,而没有进行任何验证或清理,可能导致注入攻击或其他安全漏洞。 - 信息泄露:直接将解析后的数据通过
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/');
解释
- 数据累积优化:使用
body
数组来存储数据片段,并在end
事件触发时将其合并为完整数据。 - 错误处理:添加了
try...catch
块来捕获并处理解析过程中的异常。 - 数据验证:建议在解析后进行必要的数据验证和清理,以确保数据的安全性。
- 响应格式:使用
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 楼说得很好。大概也就他们说的那样了。
在这个示例代码中,存在效率和安全问题。我们逐个分析:
效率问题
-
内存使用问题:
data
变量用于存储接收到的数据片段,每次接收新的数据块时都会进行字符串拼接操作。- 字符串在 JavaScript 中是不可变对象,这意味着每次拼接都会创建一个新的字符串对象,消耗大量内存和 CPU 资源。
-
异步处理不当:
- 事件监听器没有正确地处理错误或超时情况,可能会导致资源泄露或程序阻塞。
安全问题
-
未验证输入:
- 代码直接将接收到的数据解析为查询字符串(
querystring.parse(data)
),这可能导致注入攻击,例如通过发送恶意构造的 POST 数据来执行任意命令。
- 代码直接将接收到的数据解析为查询字符串(
-
缺少安全头信息:
- 没有设置适当的 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 防护头信息,提高了应用的安全性。
通过这些改进,代码不仅在性能上有所提升,而且安全性也得到了加强。