Azure DocumentDB参数化存储过程

时间:2016-03-13 19:14:35

标签: node.js sql-injection azure-cosmosdb nosql

寻找参数化存储过程的正确方法,以避免注入攻击。我可以像“前缀”一样以类似的方式传递一个参数,但是不知道在没有做“id =”+ id之类的情况下处理@id是正确的,这会导致避免注入攻击。

var sproc= 'dbs/{db}/colls/{col}/sprocs/GetDocument';
var  parameters = [
   {
            name: '@id',
            value: 'AndersenFamily'
   }
]

client.executeStoredProcedure(sproc,parameters , function (err, results, responseHeaders) {
            console.log('//////////////////////////////////');
            if (err) {
                console.log('// err');
                console.log(err);
            }
            if (responseHeaders) {
                console.log('// responseHeaders');
                console.log(responseHeaders);
            }
            if (results) {
                console.log('// results');
                console.log(results);
            }
            console.log('//////////////////////////////////');
});

// STORED PROCEDURE
function GetDocument(prefix) {
    var collection = getContext().getCollection();

    // Query documents and take 1st item.
    var isAccepted = collection.queryDocuments(
        collection.getSelfLink(),
        'SELECT * FROM root r WHERE r.id=@id',
        function (err, doc, options) {
            if (err) throw err;

            // Check the feed and if empty, set the body to 'no docs found', 
            // else take 1st element from feed
            if (!doc || !doc.length) getContext().getResponse().setBody('no doc found');
            else getContext().getResponse().setBody(prefix + JSON.stringify(doc[0]));
        });

    if (!isAccepted) throw new Error('The query was not accepted by the server.');
}

1 个答案:

答案 0 :(得分:1)

你很亲密。一些事情:

  • 我认为你已经将sproc的参数与查询的参数化混淆了。
  • 如果isAccepted返回false,则无需抛出错误或返回错误字符串。你得到一个假的包裹你的sproc后有一些缓冲时间。很有可能,它会及时完成,如果它关闭了,你可能会很幸运并在它超时之前完成回报。如果它强行超时,那么Doc​​uemntDB无论如何都会返回错误。

所以,你可以这样做:

var sprocLink = 'dbs/{db}/colls/{col}/sprocs/GetDocument';

client.executeStoredProcedure(sprokLink, "AndersenFamily" , function (err, results, responseHeaders) {
  console.log('//////////////////////////////////');
  if (err) {
    console.log('// err');
    console.log(err);
  }
  if (responseHeaders) {
    console.log('// responseHeaders');
    console.log(responseHeaders);
  }
  if (results) {
    console.log('// results');
    console.log(prefix + JSON.stringify(results));
  }
  console.log('//////////////////////////////////');
});

存储过程:

function GetDocument(family) {
  var collection = getContext().getCollection();

  // Query documents and take 1st item.
  var parameters = [{name: '@id',  value: family}];
  var query = 'SELECT * FROM root r WHERE r.id=@id';
  var querySpec = {query: query, parameters: parameters};
  var isAccepted = collection.queryDocuments(
    collection.getSelfLink(),
    querySpec,
    function (err, doc, options) {
      if (err) throw err;
      return getContext().getResponse().setBody(doc[0]);
    });
}

如果我理解你的意图,就没有理由将prefix传递给sproc。如上所示,当您从sproc返回时格式化输出时,可以更有效地添加它。如果我误解了您的意图并且您确实希望将其用于sproc内部的某些内容,则可以使用数组["AndersonFamily", "some prefix"]或作为对象{name: "AndersonFamily", prefix: "some prefix"}来代替" AndersonFamily& #34;我在上面的例子中展示了。

我按原样离开了您的查询,因为它会以这种方式工作,但如果您真正想做的就是按ID获取一个文档,那么使用readDocument()可能更有效率而不是queryDocuments()。我会做一个实验来看。如果切换到该方法,您将要使用基于id的路由,这意味着您需要将数据库和集合名称传递到sproc中。

在这种情况下,使用如此高度选择性的查询无关紧要,但强大的sproc会处理延续令牌甚至重新启动sproc执行。

注意,我实际上还没有运行上面的代码。我刚刚进行了文本编辑,因此很可能我的语法错误,但这个答案至少可以让你理解这一点。