假设我们有以下字符串:
"SELECT * FROM table WHERE field1 =:field1Param AND field2 IN (:field2Param)">
我想替换$ p {someName}的占位符:someName,这意味着上面的字符串将变成:
"SELECT * FROM table WHERE field1 = $ p {field1Param} AND field2 IN ($ p {field2Param})">
在Java中做到这一点的最好方法是什么?我实现了自己的手动解决方案,但它看起来又大又丑。我觉得有更好的办法。
你想要的是非常非常困难的。毕竟,SQL实际上并不是常规的。您必须编写一个SQL解析器,这并不容易。例如,SELECT * FROM foo WHERE x IN (':field1ParamHello')
,它是否应该被替换?
更一般地说,为什么要这样做?允许受污染的(例如,来自您不隐式信任的源)进入像这样的SQL查询是一个巨大的安全漏洞。唯一安全的方法是使用PreparedStatement
,然后使用.setString()
设置参数。
在此基础上构建了抽象,它们甚至使用占位符。像JOOQ和jdbc这样的库。这些都是安全的方法。试图解析SQL(甚至是一个解决方案,似乎不可能工作,如使用一个正则表达式,因为SQL不是规则的)听起来像你写的代码工作得很好…直到一年后,突然你的系统被一些有进取心的黑客拥有,有人被解雇或更糟。
对于我来说,这看起来像是一个用regex替换all的例子,它看起来像这样。
public class Main {
public static void main(String[] args) {
String sql = "SELECT * FROM table WHERE field1 = :field1Param AND field2 IN (:field2Param)";
sql = sql.replaceAll(":([a-zA-Z0-9]+)", "\$P{$1}");
System.out.println(sql);
}
}
看看这个