动态列名使用预处理语句+ sql查询,变量包含's

时间:2017-05-13 20:03:44

标签: java mysql sql jdbc

我的查询

attributes.replace(" ' ", "");
//also used SET "+attributes+" 
String sql;
sql = "UPDATE diseaseinfo"
        + " SET ?=?"
        + "WHERE companyname = 'mycom' && diseaseName =?";

PreparedStatement preparedStmt = connects.prepareStatement(sql);
preparedStmt.setString(1, attributes);
preparedStmt.setString(2, attrData);
preparedStmt.setString(3, medname);
System.out.println(preparedStmt);

它给了我一个错误,因为查询在字符串中设置了列名,所以它在原因

上变成了这样
 UPDATE diseaseinfo SET 'causes'='abc' WHERE companyname = 'mycom'  and diseaseName ='fever'

通过这个问题,我知道我无法通过预先准备的声明添加动态列:https://stackoverflow.com/a/3136049/7794329

现在,真正的问题出现了:假设我将使用像这个问题中的简单更新查询:jdbc dymanic sql query with variable containg 's

它表示你不能在简单的sql查询中输入值,因为它会再次出现查询语法错误,例如:

SELECT * FROM diseaseinfo WHERE diseaseName = 'Adult Still's disease' AND name = 'add';

这里不会执行,因为''成人静止'

然后它不适用于简单查询。我现在应该怎么做?用什么?要设置动态列,请在查询中使用。

我不担心SQL注入,因为我正在本地工作。我只想让我的查询被执行。

2 个答案:

答案 0 :(得分:4)

右。我们不能将标识符作为绑定参数提供。列的名称必须是SQL文本的一部分。

我们可以使用以下内容动态地将列的名称合并到SQL文本中:

  sql = "UPDATE diseaseinfo"
      + " SET `" + colname + "` = ?"
      + " WHERE companyname = 'mycom' AND diseaseName = ?";

并为剩下的两个绑定参数提供值

  preparedStmt.setString(1, attrData);
  preparedStmt.setString(2, medname);

关于SQL注入你是完全正确的。

在SQL注入方面,作为绑定值提供,attrDatamedname值中的单引号不会成为问题。

但是,如果我们没有保证colname是“安全的”,那么通过将colname变量合并到SQL文本中,我提供的示例是易受攻击的“包括在声明中。

因此,我们需要将值分配给colname“安全”。

我们可以使用几种方法来做到这一点。最安全的是“白名单”方法。在colname包含在SQL文本中之前,代码可以确保只将特定的“安全”值分配给colname

举个简单的例子:

  String colname;
  if (attributes.equals("someexpectedvalue") {
      colname = "columnname_to_be_used";
  } else if (attributes.equals("someothervalid") {
      colname = "valid_columname";
  } else {
     // unexpected/unsupported attributes value so
     // handle condition or throw an exception 
  }

更灵活的方法是确保colname中不会出现反引号字符。在该示例中,colname的值通过将其封装在反引号中而转义。因此,只要colname中没有出现反引号字符,我们就会阻止将提供的值解释为除标识符之外的任何内容。

对于使用硬编码反引号字符的更通用(且复杂)的方法,我们可以考虑使用supportsQuotedIdentifiers类的getIdentifierQuoteStringjava.sql.DatabaseMetaData方法。

(在OP代码中,我们没有看到attributes的内容的数据类型。我们看到一个名为replace的方法的调用,以及提供给它的参数。假设attributes是一个字符串,它应该是一个列名,我们不清楚为什么我们在字符串中有“空格单引号空间”,或者为什么我们需要删除它。除此之外,这个答案没有解决这个问题。)

答案 1 :(得分:0)

你问了一个有趣的问题..解决方案已经存在,因为YCF告诉你..如果你写

attributes.replace(" ' ", "");

然后空间也会计算

所以使用

attributes.replace("'", "");

使事情有效我也想添加

编写正确的字符串转义实用程序StringEscapeUtils.escapeSql(String)(请注意,这是非常重要的,因为该方法已从更新版本的StringEscapeUtils中删除)。 -