【问题标题】:quick and dirty SQL string escaping快速而肮脏的 SQL 字符串转义
【发布时间】:2011-08-10 06:13:33
【问题描述】:

我正在对带有 postgresql 数据库的 Web 应用程序的家庭滚动 QueryBuilder 类进行最后润色。它对所有查询使用PreparedStatement,并防止 SQL 注入。

但是,我想要一种“快速而肮脏”的方式来表示 QueryBuilder 及其 toString() 方法,仅用于调试目的。该方法将按照通常传递给PreparedStatement 的方式组装查询字符串,然后简单地将字符串中的每个? 替换为其对应的单引号值。 toString() javadoc 将警告其他开发人员这是一个不安全的近似值,仅用于调试等。

我知道这些值的单引号应该加倍(即O'Connell 转义为O''Connell)。是否还有其他我忘记的特殊字符需要处理?我寻找了类似的问题,但只发现有人被骂使用PreparedStatement(他们应该这样做,让记录显示)。

编辑:不想使用第三方工具来完成这个特定的任务,我真的只想在这里快速而肮脏。不过,我确实很欣赏这些链接 - 我可能会考虑将它们用于其他用途。

最后编辑:感谢大家的帮助。我只想为任何从谷歌偶然发现这里的人补充一点,不要使用这些技巧来访问数据库,使用PreparedStatement

【问题讨论】:

    标签: java sql postgresql escaping


    【解决方案1】:

    对于“快速而肮脏”的转义,将撇号加倍就足够了。请注意字符串文字中已经存在的问号:

    SELECT column FROM table WHERE column = 'A question?' or column = ?
    

    您不想替换第一个问号。此外,应注意这些极端情况:

    SELECT /* Is this a comment?? */ * FROM table
    -- -- --  Another comment??
    WHERE column = ?
    

    该语句中只有一个绑定值。不过,对于一个不那么快速和肮脏的解决方案,您可以使用像 jOOQ 这样的库来解决这个问题(免责声明:我为 jOOQ 背后的公司工作)。它会为你做内联,也为更讨厌的数据类型:

    DSLContext ctx = DSL.using(SQLDialect.POSTGRES);
    Object[] bindValues = { 1, "a'bc", Date.valueOf("2012-09-24"), "xy".getBytes() };
    String string = ctx.query(
      "SELECT 1 WHERE A = ? AND B = ? AND C = ? AND D = ?",
      bindValues).toString();
    

    上面会渲染

    SELECT 1 
    WHERE A = 1 
    AND B = 'a''bc'
    AND C = date '2012-09-24' 
    AND D = E'\\170\\171::bytea
    

    【讨论】:

      【解决方案2】:

      如果您不反对使用第 3 方开源库,那么我建议您看看 Apache Commons Lang 的 StringEscapeUtils.escapeSql(String str)

      编辑:我刚刚检查了source。它只不过是用两个单引号 ('') 替换单引号 (')。

      【讨论】:

      • 嗯,该方法似乎正在做我正在做的事情。该文档还提到了%_LIKE 子句,这让我忘记了。这很有帮助
      • 是的。编辑了我的答案,说了这么多。我倾向于只使用它们(公共库)而无需检查源代码,直到出现问题。这一次,消息来源并没有告诉我们比我们已经知道的更多的信息。
      • 注意“escapeSql”方法已被移除:commons.apache.org/proper/commons-lang/article3_0.html
      【解决方案3】:

      也许你可以看看 Apache 的StringEscapeUtils 中的escapeJava(String input)

      public static final String escapeJava(字符串输入)

      使用 Java 字符串规则转义字符串中的字符。

      【讨论】:

      • 谢谢,该方法的文档对我来说已经足够了。 +1 - 希望你不介意我接受了新用户
      • @takacsot:现在应该修复链接。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-08
      • 1970-01-01
      • 2010-09-15
      • 2012-12-05
      • 1970-01-01
      • 2010-12-02
      相关资源
      最近更新 更多