2015-09-25 43 views
0

我有在我试图创建一个基于IP user`s对API整个SQL的使用情况运行它。构建整个SQL和使用preparedStatement时

EG:用户点击API与格式/what/table/field/field_value?name=value1

public static Result getRows(String what, String table, String field, String field_value, String more_where_clause) throws SQLException { 
    //more_where_clause will have as many condition for where clause 

      String sql = String.format("select ? from ? where ?=?"); 

      if (!where.equals("")) { 
       sql += String.format(" and ?"); 
      } 
      ResultSet rs = targetDB.query(sql, what, table, field, field_value, more_where_clause); 



public <T extends Comparable<T>>ResultSet query(String sql, T... args) throws SQLException { 
    ResultSet rs = null; 
    try{ 
     preparedStatement = conn.prepareStatement(sql); 

     for(int i=0; i<args.length; i++){ 
      preparedStatement.setObject(i + 1, args[i]); 
     } 
     rs = preparedStatement.executeQuery(); 
    } 
    catch(SQLException e) 
    { 
     e.printStackTrace(); 
    } 
    return rs; 
} 

但是,当我查询它用说:

/name/user_table/first_name/john?last_name=doe 

我得到一个SQL字符串像

select 'name' from 'user_table' where 'first_name'='john' and 'last_name=doe' 
as    preparedStatement.setObject(i + 1, args[i]); 

推断它作为字符串。

什么是更好的方式来做到这一点,也避免SQL注入。 编辑: 除了参数化where子句部分之外,还可以进行其他额外的检查吗?如何处理more_where_clause,用户可以在where条件中输入更多内容。

+0

如果您基本上让用户注入_everything_,包括表名(您不能将其作为绑定变量并需要连接到查询字面值中),则无法避免SQL注入。通常情况下,您只需让用户输入_values_列,然后您可以通过准备好的语句安全地进行清理。 –

+0

所以我无法将它与bcoz绑定为相同的原因,即'user_table''额外'引号的'名称'。对? – user2601010

+0

http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html –

回答

2

您不能绑定名称(场,表格等),就值。

根据您可以定义一个“白名单”正则表达式来检查名称符合您的限制安全原则(即只允许[A-ZaZ0-9_-]+

较贫穷的解决方案是定义一个“黑名单”上你禁止使用双引号(")和转义序列(如果涉及多个RDBMS引擎,那可能很痛苦),然后将所有名称放在双引号之间。使用双引号时请注意案例的真实性。

您还可以检查OWASP librairies。我知道他们提供API来处理HTML,CSS,JavaScript & HTTP注入。可能他们也定义了API来处理生成的SQL。

最终你也可以建立/查询数据库,元数据和对提供者的匹配对象名称。在这种情况下,你可以依靠价值绑定。在这种情况下,不要忘记使用从元数据返回的值,并将它们用生成的SQL中的双引号引起来。

+0

这是一个很好的soln https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringEscapeUtils.html,虽然我听说过其他方面。 – user2601010

+0

注意,'StringEscapeUtils.escapeSql'只处理值而不是名称。 – LoganMzz

+0

statement.executeQuery(“SELECT * FROM MOVIES WHERE TITLE ='”+ StringEscapeUtils.escapeSql(“McHale's Navy”)+ “'”);如果我做statement.executeQuery(“SELECT * FROM MOVIES WHERE StringEscapeUtils.escapeSql(”TITLE“)='”+ StringEscapeUtils.escapeSql(“McHale's Navy”)+ “'”);那会失败? – user2601010

相关问题