我对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"污染了#34;与__proto__
提前感谢您提供任何帮助
答案 0 :(得分:2)
问题似乎来自urlencoded
中间件,Express 3
附带的中间件。
可能的解决方案不是使用Express bodyParser,而是使用body-parser
模块。
而不是
app.use(express.urlencoded())
你可以写
var bodyparser = require('body-parser')
..........
app.use(bodyparser.urlencoded())
问题似乎来自qs
模块(express 3
模块使用的版本)。它强制在它构建的对象上添加__proto__
。最后一个版本没有这个问题。
答案 1 :(得分:0)
__proto__
是一些javascript实现中包含node / v8的所有对象的特殊/自动/内部属性。我没有看到猫鼬做这种事情。将传递给模型构造函数的属性转换为模型/文档实例is here的代码。虽然我没有看到任何可疑的东西。
您是否确切知道发生了哪些情况,并且您确定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__
。
答案 2 :(得分:0)
我知道问问题已经有5年了,但实际上我昨天也遇到了同样的问题。
我有个好消息要分享-看来猫鼬5.3.9 确实解决了这个问题。您可以使用包含Android Studio
的对象来创建新模型。不过,不确定将来是否还会持续。
此外,qs模块也可以升级到最新版本以解决此问题。
用于测试的代码:
__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
})
然后,在调用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__
有趣的事实-这种行为已随着时间而改变。在节点v0.10.28中,两个代码段(很好,用var代替let;)产生空数组。
另一个有趣的事情是,较新版本的qs模块以不同的方式创建对象,因此不再导致此问题。