2012-03-30 97 views
2

我知道使用預準備語句有助於避免sql注入。我的問題是,準備好的聲明通常是非常靜態的。我遇到了一個問題,在運行時根據用戶輸入構建sql-query的where子句。根據哪些輸入字段被填充,我必須將相關語句添加到where子句。如何通過準備好的陳述來實現這一點?如何在Java中創建動態預準備語句?

回答

3

我想你可以根據他們想要查詢的列動態地構建你準備好的語句,即使用一個StringBuffer和一個循環來根據需要的列建立它們。

爲了提高效率,您應該將這些保存在某種內存查找中。所以你最終會得到一個Map或者其他準備好的語句集合,其中檢索關鍵字是它們設計用於查詢的列。

+0

好的,但這也意味着我也必須保留與我創建的SQL查詢參數列表,因爲值的添加只能與索引。我對嗎? – Mnementh 2012-03-30 13:25:33

+0

是的,你需要保持參數列名在緩存中進行查找,你還需要保持他們的順序或者以某種方式(字母?)預測順序,以便知道哪個「?」用您的查詢數據替換。希望這是有道理的,SQL不是我的第一語言:) – Jonathan 2012-03-30 13:31:06

+0

儘可能容易,但我可以管理。謝謝。 – Mnementh 2012-03-30 13:53:42

2

如果你只想要從sql注入保護,在運行時構造查詢是好的,只要你不插入任何用戶發送到查詢(但插入子句,如果用戶發送至少在字段中的東西是好)。

表現 - 我不知道。也許數據庫會緩存準備好的語句,所以如果你再次構造完全相同,它會更快,否則它不會。我不知道如何找出答案。

+0

來自PreparedStatement的JavaDocs「表示預編譯的SQL語句的對象」。基於此我不相信數據庫來緩存它們,我寧願自己緩存它們。如果當然你可以隨時分析。但它可能會更快地實施緩存;) – Jonathan 2012-03-30 13:23:08

+0

acording http://www.theserverside.com/news/1365244/Why-Prepared-Statements-are-important-and-how-to-use-them-適當的緩存可以通過連接池完成。 – Alpedar 2012-03-30 13:58:09

0

如果您使用Hibernate,Criteria Queries API是避免使用字符串連接來構建SQL查詢的好工具。使用普通的JDBC,你必須使用一個StringBuffer,就像@Jhonatan所說的那樣。

2

如果您正在根據用戶選擇的選項創建查詢中的where /和clause,那麼我猜測,您已經知道要按順序對查詢進行哪些更改獲取所需的數據。如果是這種情況,那麼您可以創建方法,將用戶要求的選項作爲方法的參數,方法構建查詢並返回該查詢。

//something similar to the following 
public String buildQuery(int option){ 
    StringBuilder sb = new StringBuilder(); 
    sb.append("select fields from table"); 
    switch(option){ 
    case 1: 
    //build query and append to sb 
    sb.append("where clause for option1"); 
    case 2: 
    //build query and append to sb 
    sb.append("where clause for option2"); 
    default: 
    // build query using default 
    sb.append("default where clause"); 
    } 

    return sb.toString(); 
} 
// create the stored procedure 
PreparedStatement ps = conn.prepareStatement(buildQuery(2)); 
ResultSet rs = ps.executeQuery(); 

現在,如果你需要臨時使用特定的用戶在查詢中輸入的值,可以存儲它們在列表或地圖,然後進行設置。

ps.setString(1,list.get(0)); 
ps.setString(2,list.get(1)); 
ResultSet rs = ps.executeQuery(); 

有probbaly更elegeant解決問題,但我們有一個查詢,使用用戶的輸入來構建查詢記錄的數據庫的應用程序,它已經在過去兩年工作的罰款。希望有所幫助。

-1

聲明一個方法並通過該方法傳遞userinput。然後根據您在preparestement對象中的輸入數據類型使用setStringsetLong