从用户输入中获取查询

时间:2018-07-07 20:11:41

标签: c# sql entity-framework security sql-injection

我需要实现一个休息端点,该端点应接受查询作为输入。如下所示:

  

api.com/api/v1/users/(registrationDate eq'2018-07-01')AND((高度gt 160)或(高度lt 68))

这种查询将不需要任何联接。实体的所有字段都可以包含在查询中。

我想到的第一件事是将查询输入直接转换为sql查询的where子句,

Dictionary<string, string> Operators = new Dictionary<string, string>
{
    { " eq ", " = " },
    { " ne ", " != " },
    { " gt ", " > " },
    { " gte ", " >= " },
    { " lt ", " < " },
    { " lte ", " <= " }
};

public string SQLify<T>(string query)
{
    if (query == null)
    {
        return $"SELECT * FROM [{typeof(T).Name}]";
    }

    foreach (var op in Operators)
    {
        query = query.Replace(op.Key, op.Value);
    }

    return $"SELECT * FROM [{typeof(T).Name}] WHERE ({query})";
}

并像这样使用它:

query = queryService.SQLify<User>(query);
var users = DbContext.Users.SqlQuery(query);

但是您可能会猜到,我非常担心它可能带来的安全隐患。我实际上尝试编写一些验证方法,检查方括号的嵌套,并检查所提到的字段实际上是类T的成员,但我确定它们提供的安全性将不足。

在这种情况下最好的方法是什么?

2 个答案:

答案 0 :(得分:1)

也许带有OData端点的WebAPI应该可以解决问题。

答案 1 :(得分:1)

您应该构建端点,以便它对参数使用参数化查询,并将其他元素(表,运算符和列)列入白名单。

您已经为操作员提供了白名单,但是您应该从头开始构建SQL,并丢弃(或错误删除)与白名单不符的内容,而不是替换现有字符串。

如果有数据授权(并非每个人都可以从端点访问所有数据),则还需要在端点中考虑这一点。