2009-06-19 159 views
14

是否有与PHP的mysql_real_escape_string()等价的Java?PHP的mysql等价物mysql_real_escape_string()

这是为了在将它们传递给Statement.execute()之前转义SQL注入尝试。

我知道我可以使用PreparedStatement来代替,但我们假设这些是一次性语句,所以准备它们将导致lower performance。我已经将代码改为使用PreparedStatement,但考虑到现有代码的结构,escape()函数会使代码更改变得更简单,以便于检查和维护;我更喜欢容易维护代码,除非有额外复杂性的令人信服的理由。 PreparedStatements也由数据库以不同方式处理,因此这可能会使我们发现我们以前没有遇到过的数据库中的错误,在发布到生产之前需要进行更多测试。

Apache StringEscapeUtils escapeSQL()只能转义单引号。

后记: 我继承的环境中有许多微妙之处,我故意避免在我的问题中。

两点考虑:

1)预处理语句是不是万能的,不提供对SQL注入100%的保护。一些数据库驱动程序使用不安全的字符串连接实例化参数化查询,而不是将查询预编译为二进制形式。另外,如果你的SQL依赖于存储过程,你需要确保存储过程本身不会以不安全的方式构建查询。

2)最准备好的语句实现将语句绑定到语句实例化的数据库连接上。如果您正在使用数据库连接池,则需要注意
仅使用准备好的语句引用与其准备的连接。一些池化机制确实透明地实现了这一点。否则,您可以汇总准备好的语句,或者(最简单但更多的开销)为每个查询创建一个新的准备好的语句。

+0

您喜欢易维护的代码,但你宁愿使用手动串逃逸,而不是PrearedStatement? – skaffman 2009-06-19 15:11:46

+1

考虑到现有的代码(我没有写),是的,它会更容易维护。 – 2009-06-19 15:16:57

+1

较低的性能可能比安全风险更具吸引力。安全处罚可能太高。在应用程序初始化代码中准备你的语句,并且惩罚可能是不明显的(当然,取决于应用程序)。 – Cheekysoft 2009-06-22 16:33:56

回答

12

据我所知,没有“标准”的方式来做到这一点。

我强烈建议尽管您目前的担忧使用准备好的语句。性能影响可以忽略不计 - 我们也有类似的情况,每秒几千条语句 - 其中大多数也是一次性的。

您获得的安全性应该高于您尚未见过的性能问题。在我看来,这是“不要过早优化”的明确情况。

在任何情况下,如果您以后发现遇到性能问题,确保准备好的语句真的是通过分析仔细分析然后寻找替代品的原因。直到那时你应该避免试图逃避权利的麻烦。

这更重要,因为我推断你正在开发某种面向公众的网站 - 内部应用很少有足够的流量来关心性能。

+1

谢谢你回答我问的问题! – 2009-06-19 15:17:41

5

不要认为PreparedStatements比较慢。尝试一下,衡量一下,然后再判断。

的PreparedStatement应该始终优先于声明来使用,几乎无一例外,尤其当SQL注入攻击是你要躲避什么。

3

避免SQL注入的唯一合理方法是使用准备/参数化语句。

例如PreparedStatement您试图避免出于某种原因。如果你做一次性陈述,准备时间应该可以忽略不计(“一次性”和“性能至关重要”是矛盾的,恕我直言)。如果你在循环中做事情,准备好的语句甚至会导致性能增加。

6

这是一些代码,它可以实现你正在寻找的东西。最初在Vnet Publishing维基上。

https://web.archive.org/web/20131202082741/http://wiki.vnetpublishing.com/Java_Mysql_Real_Escape_String

/** 
    * Mysql Utilities 
    *   
    * @author Ralph Ritoch <[email protected]> 
    * @copyright Ralph Ritoch 2011 ALL RIGHTS RESERVED 
    * @link http://www.vnetpublishing.com 
    * 
    */ 

package vnet.java.util; 

public class MySQLUtils { 

    /** 
     * Escape string to protected against SQL Injection 
     * 
     * You must add a single quote ' around the result of this function for data, 
     * or a backtick ` around table and row identifiers. 
     * If this function returns null than the result should be changed 
     * to "NULL" without any quote or backtick. 
     * 
     * @param link 
     * @param str 
     * @return 
     * @throws Exception 
     */ 

    public static String mysql_real_escape_string(java.sql.Connection link, String str) 
      throws Exception 
    { 
     if (str == null) { 
      return null; 
     } 

     if (str.replaceAll("[[email protected]#$%^&*()-=+~.;:,\\Q[\\E\\Q]\\E<>{}\\/? ]","").length() < 1) { 
      return str; 
     } 

     String clean_string = str; 
     clean_string = clean_string.replaceAll("\\\\", "\\\\\\\\"); 
     clean_string = clean_string.replaceAll("\\n","\\\\n"); 
     clean_string = clean_string.replaceAll("\\r", "\\\\r"); 
     clean_string = clean_string.replaceAll("\\t", "\\\\t"); 
     clean_string = clean_string.replaceAll("\\00", "\\\\0"); 
     clean_string = clean_string.replaceAll("'", "\\\\'"); 
     clean_string = clean_string.replaceAll("\\\"", "\\\\\""); 

     if (clean_string.replaceAll("[[email protected]#$%^&*()-=+~.;:,\\Q[\\E\\Q]\\E<>{}\\/?\\\\\"' ]" 
      ,"").length() < 1) 
     { 
      return clean_string; 
     } 

     java.sql.Statement stmt = link.createStatement(); 
     String qry = "SELECT QUOTE('"+clean_string+"')"; 

     stmt.executeQuery(qry); 
     java.sql.ResultSet resultSet = stmt.getResultSet(); 
     resultSet.first(); 
     String r = resultSet.getString(1); 
     return r.substring(1,r.length() - 1);  
    } 

    /** 
     * Escape data to protected against SQL Injection 
     * 
     * @param link 
     * @param str 
     * @return 
     * @throws Exception 
     */ 

    public static String quote(java.sql.Connection link, String str) 
      throws Exception 
    { 
     if (str == null) { 
      return "NULL"; 
     } 
     return "'"+mysql_real_escape_string(link,str)+"'"; 
    } 

    /** 
     * Escape identifier to protected against SQL Injection 
     * 
     * @param link 
     * @param str 
     * @return 
     * @throws Exception 
     */ 

    public static String nameQuote(java.sql.Connection link, String str) 
      throws Exception 
    { 
     if (str == null) { 
      return "NULL"; 
     } 
     return "`"+mysql_real_escape_string(link,str)+"`"; 
    } 

} 
2

org.apache.commons.lang.StringEscapeUtils.class在公地lang.jar能够解决您的问题!

0

根据Daniel Schneller的说法,在Java中没有标准的方法来处理PHP的mysql_real_escape_string() 我所做的就是链接replaceAll方法来处理可能需要避免任何异常的每个方面。下面是我的示例代码:

public void saveExtractedText(String group,String content) { try { content = content.replaceAll("\\", "\\\\") .replaceAll("\n","\\n") .replaceAll("\r", "\\r") .replaceAll("\t", "\\t") .replaceAll("\00", "\\0") .replaceAll("'", "\\'") .replaceAll("\\"", "\\\"");

 state.execute("insert into extractiontext(extractedtext,extractedgroup) values('"+content+"','"+group+"')"); 
    } catch (Exception e) { 
     e.printStackTrace(); 

    }