【问题标题】:How to allow only certain document fields to be inserted and updated in Meteor?如何只允许在 Meteor 中插入和更新某些文档字段?
【发布时间】:2015-08-28 03:25:42
【问题描述】:

我正在使用 Meteor,我担心可能存在安全漏洞。我只希望用户能够创建修改数据库中的某些字段。对于此示例,我希望他们能够创建或更新的唯一内容是聚会的 namedescription 字段。

Parties.allow({
  insert: function (userId, party) {
    return userId && party.owner === userId;
  },
  update: function (userId, party, fields, modifier) {
    return userId && party.owner === userId;
  },
});

这是我在 Angular Meteor 教程中看到的代码,但看起来有人可以使用 Minimongo 在浏览器的控制台中添加他们想要的任何字段。有没有一种方法可以轻松定义正确的字段,并拒绝所有不使用这些字段的插入和更新?我可以编写一个简单的函数来进行更新:

function ensureFieldsAreOk(acceptableFields,fieldsInQuestion){
    for(i = 0; i < fieldsInQuestion.length; ++i){
        if(acceptableFields.indexOf(fieldsInQuestion[i]) === -1){
           console.log("Hacking attempt detected");
           return false;
        }
    }
    return true;
}

要为插入命令执行此操作,我可以使用相同的函数,使用 Object.keys(party) 作为可接受的字段列表。

我无法想象我是第一个想到这个的人;必须有一个标准的方法来处理这个问题。

【问题讨论】:

标签: javascript mongodb security meteor


【解决方案1】:

要限制与集合关联的字段,您可以使用 https://atmospherejs.com/aldeed/simple-schemahttps://atmospherejs.com/aldeed/collection2

您可以定义字段、它们的类型、默认值和许多其他选项。

至于确保用户只能更新特定字段,您可以使用更新允许/拒绝规则中的 fieldNames 属性进行检查:

update: function (userId, doc, fieldNames, modifier) { 
    // check fieldNames here.
}

【讨论】:

    【解决方案2】:

    我认为这样做没有任何问题,而且我不知道有什么更合适的方法。你可以使用下划线来减少你的测试:

    Parties.allow({
      insert: function (userId, party) {
        return userId && party.owner === userId 
               && _.difference(_.keys(party), acceptableFields).length == 0;
      },
      update: function (userId, party, fields, modifier) {
        return userId && party.owner === userId
               && _.difference(fields, acceptableFields).length == 0
      }
    });
    

    【讨论】:

      【解决方案3】:

      别担心,你的问题是完全正确的。我在 Meteor 应用程序中处理此问题的方式是筛选正在插入或更新的文档。由于传递给insertupdate 权限函数的参数不同,我用于插入和更新的方法也不同。

      我建议直接使用以下代码或类似的代码来满足您根据上面指定的标准可能有的任何其他需求:

      Parties.allow({
          insert: function(userId, doc) {
              var allow = true;
      
              if(!userId || doc.owner !== userId) {
                  allow = false;
              }
      
              Object.keys(doc).forEach(function(docKey) {
                  if(acceptableFields.indexOf(docKey) < 0) {
                      allow = false;
                  }
              });
      
              return allow;
          },
          update: function(userId, doc, fieldNames, modifier) {
              var allow = true;
      
              if(!userId || doc.owner !== userId) {
                  allow = false;
              }
      
              fieldNames.forEach(function(fieldName) {
                  if(acceptableFields.indexOf(fieldName) < 0) {
                      allow = false;
                  }
              });
      
              return allow;
          }
      });
      

      正如您在代码示例中看到的,我已经包含了您对用户是否已登录以及用户是否是他们尝试插入或更新到数据库中的文档的所有者的检查.此外,insert 函数直接检查文档的键(显然,如果您必须像我的代码示例那样检查比顶级键更深的键,您可以进行更彻底的检查)并且如果任何不包含在其中,则允许失败可接受的字段列表。对于update函数,由于doc参数是未修改的文档,所以需要检查fieldNames参数。与insert 函数一样,如果您需要对比顶级键更深的键执行更彻底的检查,您可以直接检查modifier 参数并挖掘插入尝试中引用的每个键。有关确定最终解决方案外观可能需要的所有信息,请查看 Meteor 文档的this section

      最后,我使用通用 Javascript 编写了我的答案,以防你想采用这种方式。显然,您可以使用 Underscore 等库来增强我的建议。

      【讨论】:

        猜你喜欢
        • 2020-08-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-03
        • 1970-01-01
        • 1970-01-01
        • 2013-05-02
        • 1970-01-01
        相关资源
        最近更新 更多