2012-05-09 64 views
5

背景:逃逸SQL字符串中的Java

我目前正在開發一個企業網站管理系統數據庫(業務對象)一個Java前端。目前,我正在構建一個允許用戶構建自定義數據庫查詢的功能。我已經實施了一些措施,以確保用戶只能使用已批准用戶訪問的可用列和運算符的子集進行選擇(例如,可以在更強大的字段(如SI_CUID不能)時選擇SI_EMAIL_ADDRESS)。到目前爲止,事情一直在流行,但現在是時候確保此功能免受潛在的SQL注入攻擊。

問題:

我正在尋找逃跑用戶輸入的字符串的方法。我已經看過PerparedStatement,但是我被迫使用第三方API來訪問數據庫。這些API對我來說是不可變的,直接的數據庫訪問是不可能的。單個方法使用表示要運行的查詢的字符串,從而使PreparedStatement無效(據我所知,它必須針對直接的數據庫連接運行)。

我已經考慮使用String.replace(),但我不想重新發明輪子如果可能的話。另外,我與開發PerparedStatement的安全專家相去甚遠。

我也看過PerparedStatement的Java API參考,希望找到某種toString()方法。唉,我一直無法找到任何類似的東西。

任何幫助,非常感謝。先謝謝你。

參考文獻:

Java - escape string to prevent SQL injection

Java equivalent for PHP's mysql_real_escape_string()

回答

2

當然,使用PreparedStatement會更容易也更安全。

ANSI SQL需要一個字串開始,以單引號結束,而對於一個單引號唯一的逃生方法是使用兩個單引號:

'Joe''s Caffee' 

所以理論上,你只需要用兩個單引號替換單引號。但是,有一些問題。首先,一些數據庫(例如MySQL)也(或僅)支持反斜槓作爲轉義機制。在這種情況下,您需要加倍反斜槓(以及)。

對於MySQL,我建議使用MySQLUtils。如果你不使用MySQL,那麼你需要檢查什麼是確切的逃逸機制。

2

您可能仍然能夠使用事先準備好的聲明。看到這篇文章:get query from java sql preparedstatement。此外,根據該帖子,您可能可以使用Log4JDBC來處理此問題。

這兩個選項中的任何一個都應該可以防止您不必擔心轉義字符串以防止SQL注入,因爲準備好的語句會爲您執行此操作。

+0

那你的第一個鏈接是強大的有趣。我關心隱式定義的toString()方法的未定義行爲。企業架構師已經做出了令人印象深刻的努力,以確保數據庫本身隱藏得很好(正如他們應該)。我甚至不知道它正在運行什麼DBMS,或者它將來會不會改變。 – phobos51594

+0

其實,仔細想來,它看起來並不像PreparedStatement的,甚至有一個公開訪問的構造函數。因爲我沒有一個JDBC連接對象,我不知道我會如何連得PreparedStatment對象開始。嗯。 – phobos51594

+0

是的,我可以看到這將是一個難題。我沒有使用Log4JDBC,但它看起來可能會根據準備好的語句爲您生成SQL。 – ametren

0

雖然,有處理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(); 

}