构建查询时防止SQL注入

时间:2015-05-06 09:31:06

标签: sql-server language-agnostic

我通常知道如何使用preparedStatements来阻止它,但现在我有这样一种方法来建立查询。例如在Java中:

private String buildQuery(String where) {
    String query = "SELECT id, name FROM someTable";
    if(where.length() > 0) {
        query = query + " WHERE " + where;
    }
    return query;
}

'where'字符串就像这个'variable = value'。我怎么能在这里阻止它?我想分别传递变量和值,使用它们创建预处理语句,然后以某种方式将该预准备语句作为字符串返回,但我不确定。

3 个答案:

答案 0 :(得分:1)

这不是特定于任何一个DB API。

TL; DR:不要传递" SQL片段"周围。

不是将select语句或(子)表达式中的complete子句传递给select子句,而是传递组件,使用户数据与标识符分开。

在这种情况下,请不要传递name = value,单独传递它们。然后验证name是表的有效列,并为value部分生成参数。

因此,伪代码(我的Java生锈):

function BuildCommand(string column, object value) {
  if !IsValidColumn("theTable", column)) throw InvalidOperation(...)

  string sql = "Select column from theTable where " + column + " = @p0";

  SqlCommand cmd = new SqlCommand(sql);
  cmd.Parameters.Add("@p0", value);

  return cmd;
}

答案 1 :(得分:0)

您可以使用地图传递您的值并构建preparedStatement。检查下面的代码它应该类似于那个逻辑

public static PreparedStatement buildQuery(String where,Map<Integer, String> cond)
        throws SQLException {

    PreparedStatement stat = null;

    String query = "SELECT id, name FROM someTable " + where;

    try {
        stat = con.prepareStatement(query);

        for (Map.Entry<Integer, String> e : cond.entrySet()) {
            stat.setString(e.getKey(), e.getValue());
        }
    } catch (SQLException e ) {
        // Handle ex
    } finally {

    }
    return  stat;
}


public static void main(String[] a) throws SQLException {
    Map<Integer,String> cond =new HashMap<Integer, String>();
    cond.put(1,"val22");
    cond.put(2,"val2");


    buildQuery("col1 = ? and col2= ?", cond);
}

答案 2 :(得分:0)

我的建议是,如果参数中有where子句数组,则将函数重写为:

private String buildQuery(String[] where) {
    String query = "SELECT id, name FROM someTable";
    query = query + " WHERE "
    for(int i = 0; i < where.length; i++) {
        if(i > 0){
            query = query + " AND "
        }
        query = query + w + " = ?";
    }
    return query;
}