2012-07-16 89 views
9

我爲我的客戶提供Web服務,允許他向生產數據庫添加記錄。防止多次撥打網絡服務

我最近的事件,在我的客戶的程序員稱爲一個循環服務,迭代打電話到我的服務數千​​次。

我的問題是什麼纔是防止這種事情的最好方法。

我想到了一些方法: 1.在服務入口處,我可以更新每個調用服務的客戶端的計數器,但看起來太笨拙。 2.檢查調用此服務的客戶端的IP,並在每次調用服務時提起一個標誌,然後每隔一小時重新設置一次標誌。

我敢肯定有更好的方法,並會任何並欣賞的建議。

謝謝,大衛

+0

另一個想法,更新該用戶的會話: – 2012-07-16 08:11:59

+0

我相信你有某種「批量「添加方法? – Phil 2012-07-16 08:53:51

+0

是的,有... – 2012-07-16 08:55:30

回答

3

的方法是在會話存儲計數器並使用計數器來防止每次太多調用。

但是如果你的用戶可能會盡量避免和發送不同的cookie每次*,那麼你需要做的是像會話的自定義表,但與IP連接的用戶,而不是與cookie。

一個更這裏要說的是,如果你的IP模塊基本你可能封鎖整個公司,出來一個代理。所以最後的正確方法,但更復雜的是有ip和cookie連接用戶,並知道瀏覽器是否允許cookie。如果沒有,那麼你阻止與IP。這裏困難的部分是瞭解cookie。 在每次通話中,您都可以強制他發送與現有會話相關的有效Cookie。如果沒有,那麼瀏覽器沒有cookie。

[*] cookies與會話連接。
[*]通過製作新表來保持計數器和會話斷開連接,您還可以避免會話鎖定。

在過去,我有使用用於DosAttack代碼,但他們都不是好工作,當你有多個游泳池和複雜的應用,所以我現在用一個自定義的表,我形容它。這是兩個代碼,我有測試和使用

Dos attacks in your web app

Block Dos attacks easily on asp.net

如何找到每保存在一個表秒的點擊。以下是我計算每秒鐘點擊次數的SQL部分。其中一個竅門是,如果我從最後一次檢查中獲得6秒或更多秒,我會繼續添加點擊並計算平均值。這是從計算剪斷作爲一種思想

set @cDos_TotalCalls = @cDos_TotalCalls + @NewCallsCounter 

SET @cMilSecDif = ABS(DATEDIFF(millisecond, @FirstDate, @UtpNow)) 

-- I left 6sec diferent to make the calculation 
IF @cMilSecDif > 6000 
    SET @cClickPerSeconds = (@cDos_TotalCalls * 1000/@cMilSecDif) 
else 
    SET @cClickPerSeconds = 0 

IF @cMilSecDif > 30000 
    UPDATE ATMP_LiveUserInfo SET cDos_TotalCalls = @NewCallsCounter, cDos_TotalCallsChecksOn = @UtpNow WHERE [email protected]   
ELSE IF @cMilSecDif > 16000 
    UPDATE ATMP_LiveUserInfo SET cDos_TotalCalls = (cDos_TotalCalls/2), 
    cDos_TotalCallsChecksOn = DATEADD(millisecond, @cMilSecDif/2, cDos_TotalCallsChecksOn) 
     WHERE [email protected] 
+0

感謝您的回答,讓我說更新Session:Session [「ServiceInvoked」] = true;並詢問我們是否在會議開始時提問:if((bool)Session [「ServiceInvoked」])...我將阻止該呼叫。但是,我怎麼會重置它,讓我們說,一個小時? – 2012-07-16 08:15:43

+0

如果我將插入日期時間,我可以工作,因爲我可以檢查會議日期時間Subscract的DateTime.Now,並允許該服務是調用.... – 2012-07-16 08:17:51

+0

@DavidRasuli您一起使用上次更新的日期時間字段與計數器,然後進行平均計算 - 例如,您可以在最後一個DateTime上看到最後一次詢問是在1秒之前,並且所有就緒都有10次調用。換句話說,你把它當作最後的電話,而不是現在的電話。 – Aristos 2012-07-16 08:20:05

3

首先,你需要看看你的情況法律方面的代碼:是否與你的客戶的合同可以限制客戶端的訪問?

這個問題是出了這麼範圍的,但是你必須找到一種方式來回答這個問題。因爲如果你在法律上有義務處理所有請求,那麼就沒有辦法解決它。此外,對您的情況的法律分析可能已經包含一些限制,您可能會限制訪問。這反過來會對您的解決方案產生影響。

拋開所有這些問題,只關注技術方面,您是否使用某種用戶認證? (如果沒有,爲什麼不呢?)如果你這樣做,你可以實現你決定在每個用戶基礎上使用的任何方案,我認爲這將是最乾淨的解決方案(你不需要依賴IP地址,這是一個以某種方式醜陋的解決方法)。

一旦你有了識別單個用戶的方法,你可以實現多種限制。拳頭那些來我的心是這些:

  1. 同步處理
    纔開始處理請求所有以前的請求已被受理。這甚至可以用主處理方法中的lock聲明來實現。如果你去了這種方法,處理之間
  2. 延時請求
    需要一個處理的呼叫後,使其在下次調用之前的特定時間必須通過。最簡單的解決方案是在用戶的會話中存儲一個LastProcessed時間戳。如果你採用這種方法,你需要開始考慮如何處理新的請求,然後才允許進行處理 - 你是否向調用者發送了錯誤消息?我想你應該...

編輯
lock聲明,簡要說明:

其目的是用於線程安全的操作。的語法如下:

lock(lockObject) 
{ 
    // do stuff 
} 

lockObject需要是一個對象,當前類的通常是私有成員。其效果是,如果您有兩個線程都想要執行此代碼,第一個到達lock語句會鎖定lockObject。雖然它是這樣的,但第二個線程無法獲取鎖,因爲該對象已被鎖定。所以它只是在那裏等待,直到第一個線程退出}的塊時才釋放鎖。只有第二個線程可以鎖定lockObject並完成它,並阻止lockObject進入第三個線程,直到它退出該塊爲止。

小心,整個線程安全問題遠不是微不足道的。 (人們可以說唯一微不足道的就是程序員可以做出的許多微不足道的錯誤;-) See here在C#中的線程入門簡介

+0

偉大的答案Treb,請你詳細說一下關於「鎖」的聲明,因爲我不熟悉它? – 2012-07-16 08:22:00

+1

@David:'lock'在這裏有記錄http://msdn.microsoft.com/en-us/library/c5kehkcz(v=vs.100).aspx – Grhm 2012-07-16 08:33:22

0

獲取用戶ip並在使用web後將其插入緩存一小時服務,這是緩存在服務器:

HttpContext.Current.Cache.Insert("UserIp", true, null,DateTime.Now.AddHours(1),System.Web.Caching.Cache.NoSlidingExpiration); 

當你需要檢查用戶是否在最後一小時進入:

if(HttpContext.Current.Cache["UserIp"] != null) 
{ 
//means user entered in last hour 
}