Ama*_*man 4 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);
Run Code Online (Sandbox Code Playgroud)
它给了我一个错误,因为查询在字符串中设置了列名,所以它在原因上变成这样
UPDATE diseaseinfo SET 'causes'='abc' WHERE companyname = 'mycom' and diseaseName ='fever'
Run Code Online (Sandbox Code Playgroud)
通过这个问题我知道我不能通过准备好的语句添加动态列:https : //stackoverflow.com/a/3136049/7794329
现在,真正的问题出现了:假设我是否会使用一个简单的更新查询,比如这个问题:jdbc dymanic sql query with variable containsg 's
它说你不能在你的简单 sql 查询中输入带有 's 的值,因为它会再次使查询语法错误,例如:
SELECT * FROM diseaseinfo WHERE diseaseName = 'Adult Still's disease' AND name = 'add';
Run Code Online (Sandbox Code Playgroud)
在这里它不会执行,因为 ' 's on 'Adult Still's
那么它不适用于简单的查询。我现在该怎么办?用什么?在查询中设置动态列并处理 's。
我不担心 SQL 注入,因为我在本地工作。我只想执行我的查询。
对。我们不能提供标识符作为绑定参数。列的名称必须是 SQL 文本的一部分。
我们可以像这样动态地将列的名称合并到 SQL 文本中:
sql = "UPDATE diseaseinfo"
+ " SET `" + colname + "` = ?"
+ " WHERE companyname = 'mycom' AND diseaseName = ?";
Run Code Online (Sandbox Code Playgroud)
并为剩余的两个绑定参数提供值
preparedStmt.setString(1, attrData);
preparedStmt.setString(2, medname);
Run Code Online (Sandbox Code Playgroud)
并且您对 SQL 注入的关注是完全正确的。
在值提供为绑定值,单引号attrData和medname将不再是一个问题,在SQL注入方面。
但是,如果我们不能保证将变量包含在语句中是“安全的” ,那么我提供的示例很容易通过将 colname变量合并到 SQL 文本colname中。
所以我们需要给colname“安全”赋值。
我们可以使用几种方法来做到这一点。最安全的是“白名单”方法。代码可以确保colname在colname包含到 SQL 文本之前,只将特定的允许“安全”值分配给, 。
作为一个简单的例子:
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
}
Run Code Online (Sandbox Code Playgroud)
更灵活的方法是确保反引号字符不会出现在colname. 在该示例中,通过将其括在反引号中来对 的值colname进行转义。因此,只要反引号字符没有出现在 中colname,我们就会防止提供的值被解释为标识符以外的任何内容。
对于使用硬编码反引号字符的更通用(和复杂)的方法,我们可以考虑使用类的supportsQuotedIdentifiers和getIdentifierQuoteString方法java.sql.DatabaseMetaData。
(在 OP 代码中,我们没有看到 内容的数据类型attributes。我们看到了对名为 的方法的调用replace,以及提供给该方法的参数。假设它attributes是一个字符串,并且应该是一个列名,完全不清楚为什么我们会在字符串中包含“空格单引号空格”,或者为什么我们需要删除它。除此之外,这个答案没有解决这个问题。)