2009-10-02 37 views
4

我正在創建一個API服務,該服務允許人們向API調用提供圖像的URL,並且該服務下載要處理的圖像。如何限制Net :: HTTP請求的大小?

如何確保有人不給我像5MB圖像的URL?有沒有辦法限制請求?

這是我到目前爲止,基本上抓住了一切。

req = Net::HTTP::Get.new(url.path) 
    res = Net::HTTP.start(url.host, url.port) { |http| 
    http.request(req) 
    } 

感謝, 康拉德

回答

2

嘗試運行這個第一:

Net::HTTP.start(url.host, url.port) { |http| 
    response = http.request_head(url.path) 
    raise "File too big." if response['content-length'].to_i > 5*1024*1024 
} 

你仍然有競爭條件(你做HEAD請求後,有人可能會掉出文件),但在這是一個簡單的例子,它向服務器詢問將從GET請求發回的標頭。

+0

酷,非常感謝你!這有幫助! – chuboy 2009-10-02 21:46:44

+1

這不適用於HTTP/1.1分塊編碼或HTTO/1.0連接:關閉且無內容長度。 – panzi 2013-09-11 15:43:15

6

cwninja不幸的是你給出的答案只適用於意外攻擊。一個聰明的攻擊者將毫不費力地擊敗那張支票。他的方法不應該被使用有兩個主要原因。首先,沒有什麼能保證HEAD響應中的信息將匹配相應的GET響應。一個正常行爲的服務器肯定會這樣做,但惡意的演員不必遵循規範。攻擊者可以簡單地發送一個HEAD響應,說明它的Content-Length小於閾值,但在GET響應中提供一個巨大的文件。但是,這甚至不包括服務器使用Transfer-Encoding:chunked頭集發回響應的可能性。分塊的響應可能永遠不會結束。有些人將您的服務器指向永不停止的響應,即使您的HTTP客戶端強制執行超時,也可能會執行一項微不足道的資源耗盡攻擊。

要正確執行此操作,您需要使用HTTP庫,以便在收到字節時對它們進行計數,如果超出閾值則會中止。我可能會推薦Curb而不是Net :: HTTP。 (你甚至可以用Net :: HTTP做這件事)如果你使用on_body和/或on_progress回調函數,你可以計算傳入的字節數,並在收到一個太大的文件時中止響應。顯然,正如cwninja已經指出的那樣,如果您收到的Content-Length頭部大於您的閾值,您也想中止。路邊也是notably faster than Net::HTTP

+0

DOS的最簡單的方法是簡單地輸入一個非常緩慢的響應頁面的URL(或回到網站本身,導致DOS的反饋循環)?超時應該照顧到這一點(儘可能地),同樣的邏輯可以用於這個問題和大型響應大小問題的DOS元素。 HEAD請求提供驗證,而不是保護。 – cwninja 2009-10-11 17:42:25

+0

回到網站本身的請求通常會失敗,除非它是一個完全異步的環境,不會阻塞。但是這很容易檢查:不要允許請求到你自己的主機名。 – 2009-10-11 17:52:25

+0

黑名單幾乎總是會導致失敗。那麼http:// someproxyservice /?q = http://yoursite.com? – cwninja 2009-10-11 17:58:16

1

另一種方式來限制下載大小(完整的代碼應檢查響應狀態,異常處理等,這只是一個例子)

Net::HTTP.start(uri.host, uri.port) do |http| 
    request = Net::HTTP::Get.new uri.request_uri 
    http.request request do |response| 
# check response codes here 
     body='' 
     response.read_body do |chunk| 
      body += chunk 
      break if body.size > MY_SAFE_SIZE_LIMIT 
     end 
     break 
    end 
end