是否有一个Java相当于PHP的mysql_real_escape_string()?
这是它们传递给之前的Statement.execute逃脱SQL注入尝试()。
我知道我可以使用PreparedStatement的代替,但是让我们假设这些都是一次性语句,以便准备它们会导致性能降低 。 我已经更改为使用PreparedStatement的代码,但考虑到现有的代码是结构化的方式,一个escape()函数将使代码的修改要简单得多,审查和维护; 我更易于维护的代码除非有额外的复杂性令人信服的理由。 此外预处理语句是由数据库的处理方式不同,所以这可能使我们在数据库中的错误,我们以前没有碰到,释放到生产环境之前,需要更多的测试。
阿帕奇StringEscapeUtils escapeSQL()只逃逸单引号。
后记:有很多我继承了我在我的问题刻意回避环境的微妙。
两点考虑:
1)预处理语句是不是万能的,不提供对SQL注入100%的保护。 有些数据库驱动程序实例使用不安全的字符串连接参数化查询,而不是编译预查询,以二进制形式。 另外,如果您的SQL依赖于存储过程,你需要确保存储过程本身不建立在不安全的方式查询。
2)大多数准备好的声明中执行该语句绑定到数据库连接的语句被实例化。 如果您正在使用的数据库连接池,你必须要小心
只有它准备在连接使用准备好的语句引用。 一些统筹的机制并透明地实现这一点。 否则,你可以集中预处理语句以及或(最简单的,但更多的开销)创建的每个查询的新准备好的声明。
Answer 1:
据我所知,目前还没有“标准”的方式来做到这一点。
我强烈建议使用预处理语句,尽管当前的关注。 对性能的影响将是微不足道的 - 我们有以每秒几千陈述了类似的情况 - 大部分是单镜头为好。
你获得的安全性进行称重比你还没有见过的性能问题高得多。 在我看来,这是“不要过早优化”一个明确的情况。
在任何情况下,你应该找出来以后,你遇到性能问题,请确保准备语句是真正的原因仔细剖析,然后寻找替代品。 在那之前,你应该保存自己的努力来获得正确的逃逸的麻烦。
内部应用程序很少获得足够的流量,关注性能无论如何 - 因为我推断你正在开发某种面向公众的网站,这是更重要的。
Answer 2:
下面是一些代码,实现你在找什么。 本来在互联星空出版维基。
https://web.archive.org/web/20131202082741/http://wiki.vnetpublishing.com/Java_Mysql_Real_Escape_String
/**
* Mysql Utilities
*
* @author Ralph Ritoch <rritoch@gmail.com>
* @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("[a-zA-Z0-9_!@#$%^&*()-=+~.;:,\\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("[a-zA-Z0-9_!@#$%^&*()-=+~.;:,\\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)+"`";
}
}
Answer 3:
不要以为用预处理较慢。 试试吧,衡量它,然后判断。
预处理语句应始终优先于声明来使用,几乎无例外, 尤其是当SQL注入攻击是你要躲避什么。
Answer 4:
唯一明智的方式,以避免SQL注入是使用准备/参数化的语句。
例如, PreparedStatement的 ,你要设法避免因某种原因。 如果你做一锤子陈述,时间让他们做好准备可以忽略不计(“一步法”和“性能关键”是一对矛盾,恕我直言) 如果你在一个循环做的事情,准备的语句甚至导致性能提高。
Answer 5:
org.apache.commons.lang.StringEscapeUtils.class在公地lang.jar能够解决您的问题!
Answer 6:
据丹尼尔Schneller,有处理PHP的mysql_real_escape_string()在Java中我所做的就是以链的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(); }
Answer 7:
我不相信任何东西比的PreparedStatement,以确保安全。 但是,如果你需要有一个类似的工作流程建立查询时,你可以使用下面的代码。 它使用一个PreparedStatement下,就像一个StringBuilder,增加了逃生的功能和跟踪的参数指标为您服务。 它可以像这样使用:
SQLBuilder sqlBuilder = new SQLBuilder("update ").append(dbName).append(".COFFEES ");
sqlBuilder.append("set SALES = ").escapeString(sales);
sqlBuilder.append(", TOTAL = ").escapeInt(total);
sqlBuilder.append("where COF_NAME = ").escapeString(coffeeName);
sqlBuilder.prepareStatement(connection).executeUpdate();
下面的代码:
class SQLBuilder implements Appendable {
private StringBuilder sqlBuilder;
private List<Object> values = new ArrayList<>();
public SQLBuilder() {
sqlBuilder = new StringBuilder();
}
public SQLBuilder(String str)
{
sqlBuilder = new StringBuilder(str);
}
@Override
public SQLBuilder append(CharSequence csq)
{
sqlBuilder.append(csq);
return this;
}
@Override
public SQLBuilder append(CharSequence csq, int start, int end)
{
sqlBuilder.append(csq, start, end);
return this;
}
@Override
public SQLBuilder append(char c)
{
sqlBuilder.append(c);
return this;
}
// you can add other supported parameter types here...
public SQLBuilder escapeString(String x)
{
protect(x);
return this;
}
public SQLBuilder escapeInt(int x)
{
protect(x);
return this;
}
private void escape(Object o)
{
sqlBuilder.append('?');
values.add(o);
}
public PreparedStatement prepareStatement(Connection connection)
throws SQLException
{
PreparedStatement preparedStatement =
connection.prepareStatement(sqlBuilder.toString());
for (int i = 0; i < values.size(); i++)
{
Object value = values.get(i);
// you can add other supported parameter types here...
if (value instanceof String)
preparedStatement.setString(i + 1, (String) value);
else if (value instanceof Integer)
preparedStatement.setInt(i + 1, (Integer) value);
}
return preparedStatement;
}
@Override
public String toString()
{
return "SQLBuilder: " + sqlBuilder.toString();
}
}
文章来源: Java equivalent for PHP's mysql_real_escape_string()