繁体   English   中英

Express.js请求正文__proto__

[英]Express.js request body __proto__

我对express.urlencoded()中间件生成的request.body有一点问题。 在某些情况下,它会在request.body对象的末尾添加__proto__ ,而不能直接用于启动moongose模型,因此var user = new User(req.body)

作为一个例子,我将使用node-express-mongoose-demo存储库。 所有表单都运行正常,但app.post('/users', users.create)收到req.body“污染” __proto__

在此先感谢您的帮助

似乎问题来自urlencoded中间件, Express 3包含的中间件。

一种可能的解决方案是不使用Express bodyParser,而是使用body-parser模块。

代替

app.use(express.urlencoded())

你可以写

var bodyparser = require('body-parser')

..........

app.use(bodyparser.urlencoded())

问题似乎来自qs模块( express 3模块使用的版本)。 它强制在它构建的对象上添加__proto__ 最后一个版本没有此问题。

嗯,这很有意思。 __proto__是一些javascript实现中包含node / v8的所有对象的特殊/自动/内部属性。 我没有看到猫鼬做这种事情。 将传递给模型构造函数的属性转换为模型/文档实例的代码在此处 虽然我没有看到任何可疑的东西。

你知道究竟发生了哪些情况吗?你确定它是urlencoded做的吗? 当您尝试保存已被“污染”的用户时会发生什么? 通常,mongoose会忽略模式中未定义的字段,那么会发生什么?

您应该能够(可能?)使用如下的中间件来解决这个问题,但我很想分离并理解根本原因。 下划线/ lodash omit在这里运作良好。

var _ = require('lodash');

function unpollute(req, res, next) {
  req.body = _.omit(req.body, '__proto__');
  next();
}
app.use(express.urlencoded());
app.use(unpollute);

然后当你的路由处理程序运行时, req.body将没有__proto__

我知道自问题问题已经过去了5年,但实际上我昨天遇到了同样的问题。

我有好消息要分享 - 看起来像猫鼬5.3.9实际上解决了这个问题。 您可以使用包含__proto__对象创建新模型。 不过,不确定这是否会持续存在。

此外,qs模块可以升级到最新版本以解决此问题。

用于测试的代码:

// simulate object creation by express
let newCustomer = Object.create(null);
newCustomer.name = 'new test customer';
newCustomer.__proto__ = Object.prototype;

console.log(newCustomer); // { name: 'new test customer', __proto__: {} }
Customer.create(newCustomer, function(err, created) {
    console.log('err:', err, 'created:', created);
    // mongose 5.3.8: ValidationError: Customer validation failed
    // mongose 5.3.9: new customer created
})

更多细节:

原型是有问题的,因为qs模块使用以下方法创建新对象:

Object.create(null)

然后,当调用restoreProto时,它会尝试修复对象的原型:

obj.__proto__ = Object.prototype;

__proto__最终成为对象的可见属性:

let obj = Object.create(null);
obj.__proto__ = Object.prototype;
console.log(Object.keys(obj));
// [ '__proto__' ]

如果使用{}或甚至Object.create(Object)创建新对象,则__proto__不会出现在键枚举中,即使以相同的方式分配:

let obj = {};
obj.__proto__ = Object.prototype;
console.log(Object.keys(obj));
// []    

有趣的事实 - 这种行为随着时间的推移而改变。 在节点v0.10.28中,两个代码片段(好吧,使用var而不是let;))产生空数组。

另一个有趣的事情是,较新版本的qs模块以不同的方式创建对象,因此它不再导致此问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM