【问题标题】:How to remove __proto__ property from a JSON object?如何从 JSON 对象中删除 __proto__ 属性?
【发布时间】:2015-03-10 04:29:27
【问题描述】:

我有以下基于Node-Express的功能:

//function on server side
app.get('/loginCheck', loggedCheck, function(req, res) {
    var data = {local: {}, facebook: {}};
    data.id = req.user._id;
    data.local.email = req.user.local.email;
    data.local.fname = req.user.local.fname;
    data.local.lname = req.user.local.lname ;
    data.local.college = req.user.local.college ;
    data.local.degree = req.user.local.degree ;
    data.year = req.user.year ;
    data.mobile = req.user.mobile ;
    data.city = req.user.city ;
    data.facebook.id = req.user.facebook.id ;
    //res.json(data);        

    var x = {};
    x.name = "someName"

    res.json(x);
})

以下是客户端发出 ajax 请求的代码:

//function on client side making an ajax request
$.get("/loginCheck",function(data,status){
    console.log(data);
});

在之前的服务器端代码中,req.user 是 mongoose 创建的一个 mongodb 对象。我想要做的是发送数据对象(它具有req.user对象的一些选定属性)并将对象作为JSON作为响应发送。

变量x 是自定义创建的变量。

问题是: 当我将data 对象发送给客户端时,__proto__ 属性也会添加到当我向客户端发送x 时没有发生的对象。 但是,我不想在客户端使用__proto__,因为从一些文章中,我发现__proto__ 存在安全问题。

我需要有关如何从 data 对象中删除 __proto__ 的帮助。

【问题讨论】:

  • 您不能删除__proto__,这是一个内部属性。
  • @BhojendraSah: .__proto__ 不是内部属性,而是继承自Object.prototype
  • 安全问题?不,你一定是看错了。你能给我们指点那些文章吗?
  • res.json 将不包括 __proto__ 属性。您确定您在实际的 HTTP 响应中看到了它吗?

标签: javascript json node.js mongodb mongoose


【解决方案1】:

您可以简单地通过使用Object.create(null) 并定义您希望使用的属性来放弃对象上的原型。

var obj = Object.create(null);

Object.defineProperty(obj, {
  'foo': {
    value: 1,
    enumerable: true,

  },
  'bar': {
    value: 2,
    enumerable: false
  }
});

// or...

obj.foo = 1
obj.bar = 2

/* various checks */

obj instanceof Object; // false
Object.prototype.isPrototypeOf(obj); // false
Object.getPrototypeOf(obj); // null
obj + ""; // TypeError: Cannot convert object to primitive value
'toString' in obj; // false
foo; // 1
obj['bar']; // 2
JSON.stringify(obj); // {"foo":1}
{}.hasOwnProperty.call(obj, 'foo'); // true
{}.propertyIsEnumerable.call(obj, 'bar'); // false

在这种方法中,您不再需要检查obj.hasOwnProperty(key)

for (var key in obj) {
  // do something
}

阅读更多:True Hash Maps in JavaScript

MDN: Object.defineProperty() & Object.create()

// with __proto__

var obj = {} // equivalent to Object.create(Object.prototype);
obj.key = 'value'

console.log(obj)



// without __proto__

var bareObj = Object.create(null)
Object.defineProperty(bareObj, {
  'key': {
    value: 'value',
    enumerable: false,
    configurable: true,
    writable: true
  }
})
// or... bareObj.key = 'value'

console.log(bareObj)

【讨论】:

  • OP 似乎正在发送和解析 JSON,而您实际上别无选择。我们甚至都无法重现这个问题。
  • OP 可以将他的 JSON 映射到裸对象然后解析它:Object.keys(obj).map(key => bareObj[key] = obj[key])Object.assign(bareObj, obj)。唉,这是旧的,但想表明它可以为其他偶然发现它的人完成。
  • 这不会阻止__proto__ 在分配时调用特殊行为。任何分配给__proto__ 的东西都会被设置为原型,即使它以前从未有过。
【解决方案2】:

您不需要删除它。它不会造成任何麻烦/问题。

你可以这样使用。

$.each(data, function(k, v) {
    console.log(k, v);
});

【讨论】:

    【解决方案3】:

    从服务器发送__proto__ 可以创建一个JSON 对象,如果在没有删除__proto__ 或泄漏敏感数据的情况下将密钥传输到另一个对象,则可能会破坏。

    它出现在编码的 JSON 中是不寻常的,因为它通常被忽略。这表明其他地方可能存在问题或混乱。您正在使用的库可能会意外泄漏或使用它。在封闭系统中使用它可能是可以的,但不应允许它进出系统。

    // If is optional.
    if('__proto__' in obj)
        // This may cause unintended consequences.
        delete(obj.__proto__);
    

    在接收数据时,您还应该非常小心它不包含__proto__ 属性。如果将该密钥复制到另一个对象,这可能会导致服务器崩溃或危及服务器。

    如果创建自己的对象,有一些技巧可以改变它的行为,例如使用 defineProperty,但这些技巧往往不能完全消除问题。

    【讨论】:

    • delete obj.__proto__ 似乎并没有真正删除它
    【解决方案4】:

    随便写

    String(<put here your data>)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-15
      • 2011-01-16
      • 1970-01-01
      • 2011-05-09
      • 1970-01-01
      • 1970-01-01
      • 2022-07-06
      相关资源
      最近更新 更多