2008-08-29 113 views
194

我們在定的時間段用各種方式油門用戶操作實驗:在ASP.NET MVC中實現請求限制的最佳方法?

  • 極限提問/回答的帖子
  • 限制編輯
  • 限制飼料檢索

對於目前,我們使用緩存來簡單地插入用戶活動記錄 - 如果該記錄存​​在/當用戶執行相同的活動時,我們就進行調​​節。

使用Cache會自動爲我們提供了陳舊的數據清洗和用戶的滑動活動窗口,但如何將規模可能是一個問題。

確保請求/用戶操作可以被有效抑制(強調穩定性)的其他方法是什麼?

+0

您是想限制每個用戶還是每個問題?如果每個用戶,可以使用會話,這將是一個較小的集合。 – 2008-11-02 01:23:53

+1

這是每個用戶,但我們無法使用會話,因爲這需要cookie - 我們目前正在基於IP地址進行限制。 – 2008-11-13 02:20:59

回答

217

下面是我們一直在使用的堆棧溢出過去一年什麼的通用版本:

/// <summary> 
/// Decorates any MVC route that needs to have client requests limited by time. 
/// </summary> 
/// <remarks> 
/// Uses the current System.Web.Caching.Cache to store each client request to the decorated route. 
/// </remarks> 
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] 
public class ThrottleAttribute : ActionFilterAttribute 
{ 
    /// <summary> 
    /// A unique name for this Throttle. 
    /// </summary> 
    /// <remarks> 
    /// We'll be inserting a Cache record based on this name and client IP, e.g. "Name-192.168.0.1" 
    /// </remarks> 
    public string Name { get; set; } 

    /// <summary> 
    /// The number of seconds clients must wait before executing this decorated route again. 
    /// </summary> 
    public int Seconds { get; set; } 

    /// <summary> 
    /// A text message that will be sent to the client upon throttling. You can include the token {n} to 
    /// show this.Seconds in the message, e.g. "Wait {n} seconds before trying again". 
    /// </summary> 
    public string Message { get; set; } 

    public override void OnActionExecuting(ActionExecutingContext c) 
    { 
     var key = string.Concat(Name, "-", c.HttpContext.Request.UserHostAddress); 
     var allowExecute = false; 

     if (HttpRuntime.Cache[key] == null) 
     { 
      HttpRuntime.Cache.Add(key, 
       true, // is this the smallest data we can have? 
       null, // no dependencies 
       DateTime.Now.AddSeconds(Seconds), // absolute expiration 
       Cache.NoSlidingExpiration, 
       CacheItemPriority.Low, 
       null); // no callback 

      allowExecute = true; 
     } 

     if (!allowExecute) 
     { 
      if (String.IsNullOrEmpty(Message)) 
       Message = "You may only perform this action every {n} seconds."; 

      c.Result = new ContentResult { Content = Message.Replace("{n}", Seconds.ToString()) }; 
      // see 409 - http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 
      c.HttpContext.Response.StatusCode = (int)HttpStatusCode.Conflict; 
     } 
    } 
} 

使用範例:

[Throttle(Name="TestThrottle", Message = "You must wait {n} seconds before accessing this url again.", Seconds = 5)] 
public ActionResult TestThrottle() 
{ 
    return Content("TestThrottle executed"); 
} 

ASP.NET緩存就像一個冠軍在這裏 - 通過使用它,您可以自動清理油門條目。隨着我們日益增長的流量,我們沒有看到這是服務器上的問題。

隨時就此方法提供反饋;當我們使Stack Overflow更好時,您可以更快地獲得Ewok fix :)

9

我們使用這個網址http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspx借來的技術,不是爲了限制,但對於一個窮人的拒絕服務(D.O.S)。這也是基於緩存的,可能與您正在做的相似。你是否在阻止D.O.S.節流?攻擊?路由器當然可以用來減少D.O.S;你認爲路由器可以處理你需要的節流嗎?

+1

這幾乎是我們已經在做的 - 但它的工作效果很好:) – 2009-01-11 05:45:16

67

Microsoft對IIS 7新增了一個名爲動態IP限制擴展的擴展,用於IIS 7.0 - Beta。

「爲IIS 7.0的動態IP限制是提供針對Web服務器和Web站點上的服務和強力攻擊拒絕保護模塊。這種保護是由HTTP客戶誰做的暫時封鎖IP地址提供異常大量的併發請求或者在很短的時間內發出大量請求。「 http://learn.iis.net/page.aspx/548/using-dynamic-ip-restrictions/

實施例:

如果設置的條件來阻止X requests in Y millisecondsX concurrent connections in Y milliseconds的IP地址將被阻止爲Y milliseconds然後請求將被再次允許之後。

+1

您是否知道它是否會導致像Googlebot這樣的抓取工具出現問題? – Helephant 2013-08-23 13:17:18

相關問題