动态添加SQL PreparedStatement的列 - 仍然可以安全地防止注入?

时间:2013-01-30 00:03:27

标签: mysql jdbc prepared-statement sql-injection

我试图在我的Java程序中阻止SQL注入。我想使用PreparedStatements来执行此操作,但我事先不知道列数或其名称(该程序允许管理员在表中添加和删除列)。我是新手,所以这可能是一个愚蠢的问题,但我想知道这种方法是否安全:

public static int executeInsert( String table, Vector<String> values)
{
    Connection con;
    try {
        con = connect();

        // Construct INSERT statement
        int numCols = values.size();
        String selectStatement = "INSERT INTO " + table + " VALUES  (?";
        for (int i=1; i<numCols; i++) {
            selectStatement += ", ?";
        }
        selectStatement += ")";     
        PreparedStatement prepStmt = con.prepareStatement(selectStatement);

        // Set the parameters for the statement
        for (int j=0; j<numCols; j++) {
            prepStmt.setString(j, values.get(j));
        }

        System.out.println( "SQL: " + prepStmt) ;
        int result = prepStmt.executeUpdate();
        con.close() ;
        return( result) ;
    } catch (SQLException e) {
        System.err.println( "SQL EXCEPTION" ) ;
        System.err.println( "Inserting values " + values + " into " + table);
        e.printStackTrace();
    }
    return -1;
}

基本上我是根据传入的值来动态创建语句的String(因此表中有多少列)。我觉得它很安全,因为PreparedStatement实际上并不是在这个字符串生成之后创建的。我可以创建类似的函数来接受实际的列名并将它们合并到SQL语句中,但这些函数将由我的程序生成,而不是基于用户输入。

1 个答案:

答案 0 :(得分:2)

每当您将table等值插入查询而不进行转义时,您应该针对已知良好值的白名单进行测试。这可以防止人们创造性并造成麻烦。一个简单的字典或有效条目数组通常就足够了。

使用准备好的陈述是个好主意,但请确保您准备的陈述不允许从一开始就进行注射。