2008-11-10 31 views
5

「靜態」查詢始終保持不變。例如,Stackoverflow上的「標籤」按鈕或Digg上的「7天」按鈕。簡而言之,它們總是映射到特定的數據庫查詢,因此您可以在設計時創建它們。如何創建動態和安全的查詢

但我想弄清楚如何做「動態」查詢,其中用戶基本上決定如何在運行時創建數據庫查詢。例如,在Stackoverflow上,您可以組合標籤並按照您選擇的方式過濾帖子。這是一個動態查詢,儘管它非常簡單,因爲您可以將它們組合在標籤的世界中。一個更復雜的例子是如果你可以結合標籤和用戶。

首先,當你有一個動態查詢時,聽起來好像你不能再使用替代api來避免sql注入,因爲查詢元素將取決於用戶決定包含在查詢中的內容。除了使用字符串追加之外,我無法看到如何構建此查詢。

其次,查詢可能跨越多個表。例如,如果SO允許用戶基於用戶和標籤進行過濾,並且這些可能位於兩個不同的表中,那麼構建查詢會比僅追加列和WHERE子句複雜一些。

我該如何去執行這樣的事情?

+0

爲了建議抽象: 你用什麼語言與數據庫交談? 您正在使用哪個數據庫? – 2008-11-10 20:14:00

回答

0

那麼選項必須映射到某些東西。

如果仍然使用參數作爲選項,SQL查詢字符串CONCAT不是問題。

2

第一條規則是允許用戶在SQL表達式中指定,但不允許SQL 語法。所有查詢語法應該由您的代碼字面上指定,而不是用戶輸入。用戶指定的值可以作爲查詢參數提供給SQL。這是限制SQL注入風險的最有效方法。

許多應用程序需要通過代碼「構建」SQL查詢,因爲正如您指出的那樣,某些表達式,表連接,按條件排序等依賴於用戶的選擇。在逐個構建SQL查詢時,有時難以確保結果是有效的SQL語法。

我在一個名爲Zend_Db_Select的PHP類上工作,它提供了一個API來幫助解決這個問題。如果你喜歡PHP,你可以看看代碼的想法。它不處理任何可以想象的查詢,但它確實有很多。

其他一些PHP數據庫框架也有類似的解決方案。

1

儘管不是一個通用的解決方案,但下面是一些可以緩解動態但安全的查詢問題的步驟。

其中列值屬於基數是任意值的一組值的標準不需要是動態的。考慮使用instr函數或使用您加入的特殊過濾表。只要列數已知,此方法可輕鬆擴展到多個列。使用這種方法可以輕鬆處理用戶和標籤的過濾。

當過濾條件中的列數是任意的但很小時,請考慮對每種可能性使用不同的靜態查詢。

只有當過濾標準中的列數是任意的並且可能很大時,才應考慮使用動態查詢。在這種情況下...

爲了避免SQL注入,可以構建或獲取防禦該攻擊的庫。雖然更困難,但這不是不可能完成的任務。這主要是關於在要篩選的值中轉義SQL字符串分隔符。

爲了避免昂貴的查詢,請考慮使用專門爲此目的而製作的視圖,以及一些前期邏輯,以限制如何調用這些視圖。從開發人員的時間和精力來看,這是最具挑戰性的。

0

如果您使用python來訪問您的數據庫,我建議您使用Django model system。 python和其他語言都有很多類似的apis(特別是在軌道上的ruby)。通過避免使用SQL直接與數據庫進行對話,我節省了大量時間。

the example link

#Model definition 
class Blog(models.Model): 
    name = models.CharField(max_length=100) 
    tagline = models.TextField() 

    def __unicode__(self): 
     return self.name 

模型的使用(這是有效的INSERT語句)

from mysite.blog.models import Blog 
b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.') 
b.save() 

的查詢得到更加複雜 - 你繞過一個查詢對象,你可以添加過濾器/對元素進行排序。當你最終準備好使用查詢時,Django創建一個SQL語句,它反映了調整查詢對象的所有方法。我覺得它很可愛。

這種抽象

  • 你的模型可以與外鍵和約束數據庫表中的Django的
  • 許多數據庫的支持(PostgreSQL的,MySQL和SQL精簡版等)
  • 創建的其他優點DJango會分析您的模板並在其中創建一個automatic admin site