2012-01-04 98 views
3

環境有限請求:
Java的EE基於web的應用程序限制用戶,使每秒


問題
需要限制用戶,使超過5(例如) (主要是BOT)


解決方案
作爲基本設計我打算有2個同步Map在應用範圍

Map<String, Map<Long, Integer>> 

String是用於請求

Long SessionId是當前第二表示

Integer是保持請求數


過程:

步驟0:

配置Filter攔截每個請求

步驟1:

確定地圖 我將會看到,如果當前minute是奇數,然後我將在mapOne上添加數據,我將清除mapTwo

步驟2:

過程圖

int requestNoForThisSecond = mapXX.get(request.getSession().getId()).get(currentSecondRepresantationInLong); 
if(requestNoForThisSecond <= 5){ 
      requestNoForThisSecond++; 
      mapXX.get(request.getSession().getId()).put(currentSecondRepresantationInLong, requestNoForThisSecond); 
}else{ 
     response.sendRedirect();// redirect to some captcha page 
    } 

步驟4:

如果會話到期/用戶註銷


也刪除會話表項

這是非常基本的問題設計

你們中的任何一個人有更好的主意/建議?

+0

我不認爲這個問題與Java或Java-ee有什麼關係。沒有?我的意思是,這是關於一種方法的討論,這是與語言無關的。如果您希望我們實際檢查您的代碼,那麼適當的網站將爲CodeReview.StackExchange.com – 2012-01-04 12:38:00

+1

請參閱http://stackoverflow.com/questions/667508/whats-a-good-rate-limiting-algorithm – skaffman 2012-01-04 12:44:01

+0

@ skaffman感謝 – 2012-01-04 12:51:33

回答

0

聽起來合理,並且類似於this article中提出的Spring < - >驗證碼集成。

1

可能是一個非常糟糕的技巧,但......

實現自定義Set<Long>爲其.add()操作,如果你試圖推大於閾值相同的長值更和使用,作爲值返回false?

然後代碼是這樣:

if (!theMap.get(whatever()).add(secondInLong)) 
    // threshold reached 

一個優點是,它會在你當前的代碼禁止的競爭條件:如果只您的地圖是同步的,對會話數的檢查不受保護。有了這個解決方案,它是。或使用某種類型的鎖圍繞代碼,並使用「普通」地圖。

進一步考慮這個想法,你甚至可以實現一個帶有委託的自定義Map。然後在地圖本身內計算「長秒」表示,你不需要關心它。

1

5請求一秒鐘相當於每0.2秒一次請求。那麼,爲什麼不簡單地有一個存儲用戶的sessionID和最後System.nanoTime()的Map,然後你的過濾器只需要做一個快速評估來檢查用戶上一次請求後至少已經過了200ms。

+0

可能會出現這種情況,第一次請求在100毫秒以1000毫秒秒出現,然後用戶行爲正常。你的想法很好,但這並不完全符合規定的要求。謝謝! – 2012-01-04 12:46:39

3

首先,我認爲你應該忘記會話ID的想法,並改用IP地址。您不希望機器人向您發送必要的cookie,以便您可以跟蹤其會話,是嗎?其次,我認爲你的方法是不必要的複雜。您只需要一個IP地址到時間陣列[N]的映射,其中N是一個固定的數字,即您計劃每秒允許的請求數。 (我假設它會相對較低)。因此,每當您從給定IP發出請求時,都會將數組內容向下移一位,並將新請求的時間添加到數組末尾。然後,從最後一個索引處的時間減去數組索引0處的時間,這會給出IP向您發送N個請求所花費的時間,您可以將這些請求平均轉換爲每秒請求數。

此外,你可能會發現這個有趣的討論:https://softwareengineering.stackexchange.com/questions/126700/development-of-a-bot-web-crawler-detection-system

+2

IP地址可能不起作用,他將如何捕獲隱藏在防火牆或VPN後面的呼叫? – 2012-01-04 12:36:28

+0

s,might,will - 會話ID _is_必須在這裏使用 – fge 2012-01-04 12:42:11

+0

如果我們在討論防火牆或VPN背後的**巨大網絡,這隻會造成問題,在這種情況下,人們從它的連接將只需要一些節流。我沒有看到這個問題。 – 2012-01-04 12:54:31

1

有一個Synchronizer Token Pattern。建議使用此模式以防止雙重提交,跨站點請求僞造等。Struts廣泛使用此模式(示例在JavaRanch上提到)。


對於那些誰也不知道同步標記模式是如何工作的,這裏有雲:

  1. 用戶請求一個頁面。在服務器上,負責頁面請求的控制器從頁面檢索令牌(不是JSESSIONID)。
  2. 如果從請求返回的令牌與在會話中找到的令牌相匹配,則它是有效的令牌,繼續。
  3. 重置令牌(生成新令牌)並將其保存在會話中。因此,您可以每次進行驗證並使用新令牌返回到同一頁面。

在您的建議中,您將不得不計時提交您的提交,請檢索會話令牌(使用HttpSessionListener)並限制您的請求調用。

我希望這會有所幫助。

+0

這肯定會阻止BOT,謝謝 – 2012-01-04 13:45:12