PHP的mysql等价物mysql_real_escape_string()
是否有与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)最准备好的语句实现将语句绑定到语句实例化的数据库连接上。如果您正在使用数据库连接池,则需要注意
仅使用准备好的语句引用与其准备的连接。一些池化机制确实透明地实现了这一点。否则,您可以汇总准备好的语句,或者(最简单但更多的开销)为每个查询创建一个新的准备好的语句。
据我所知,没有“标准”的方式来做到这一点。
我强烈建议尽管您目前的担忧使用准备好的语句。性能影响可以忽略不计 - 我们也有类似的情况,每秒几千条语句 - 其中大多数也是一次性的。
您获得的安全性应该高于您尚未见过的性能问题。在我看来,这是“不要过早优化”的明确情况。
在任何情况下,如果您以后发现遇到性能问题,确保准备好的语句真的是通过分析仔细分析然后寻找替代品的原因。直到那时你应该避免试图逃避权利的麻烦。
这更重要,因为我推断你正在开发某种面向公众的网站 - 内部应用很少有足够的流量来关心性能。
谢谢你回答我问的问题! – 2009-06-19 15:17:41
不要认为PreparedStatements比较慢。尝试一下,衡量一下,然后再判断。
的PreparedStatement应该始终优先于声明来使用,几乎无一例外,尤其当SQL注入攻击是你要躲避什么。
避免SQL注入的唯一合理方法是使用准备/参数化语句。
例如PreparedStatement您试图避免出于某种原因。如果你做一次性陈述,准备时间应该可以忽略不计(“一次性”和“性能至关重要”是矛盾的,恕我直言)。如果你在循环中做事情,准备好的语句甚至会导致性能增加。
这是一些代码,它可以实现你正在寻找的东西。最初在Vnet Publishing维基上。
/**
* 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)+"`";
}
}
org.apache.commons.lang.StringEscapeUtils.class在公地lang.jar能够解决您的问题!
根据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();
}
您喜欢易维护的代码,但你宁愿使用手动串逃逸,而不是PrearedStatement? – skaffman 2009-06-19 15:11:46
考虑到现有的代码(我没有写),是的,它会更容易维护。 – 2009-06-19 15:16:57
较低的性能可能比安全风险更具吸引力。安全处罚可能太高。在应用程序初始化代码中准备你的语句,并且惩罚可能是不明显的(当然,取决于应用程序)。 – Cheekysoft 2009-06-22 16:33:56