2010-06-21 5 views
9

Sto costruendo un sito ASP.NET MVC in cui voglio limitare la frequenza con cui gli utenti autenticati possono utilizzare alcune funzioni del sito.Come si implementa la limitazione della velocità in un sito MVC ASP.NET?

Anche se capisco come funziona la limitazione della velocità, non riesco a visualizzare come implementarlo programmaticamente senza creare un odore di codice maggiore.

Puoi indicarmi una soluzione semplice ma potente per affrontare un problema del genere, con codice di esempio C#?

Se è importante, tutte queste funzioni sono attualmente espresse come azioni che accettano solo HTTP POST. Potrei eventualmente voler implementare la limitazione della velocità per le funzioni HTTP GET, quindi sto cercando una soluzione che funzioni per tutte queste circostanze.

+0

Ecco un altro tutorial completo su come farlo, che consente intervalli più flessibili: https://www.shieldui.com/blogs/rate-limiting-in-asp-net-mvc –

risposta

15

Se si utilizza IIS 7, è possibile dare un'occhiata allo Dynamic IP Restrictions Extension. Un'altra possibilità è quella di implementare questo come un filtro di azione:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] 
public class RateLimitAttribute : ActionFilterAttribute 
{ 
    public int Seconds { get; set; } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     // Using the IP Address here as part of the key but you could modify 
     // and use the username if you are going to limit only authenticated users 
     // filterContext.HttpContext.User.Identity.Name 
     var key = string.Format("{0}-{1}-{2}", 
      filterContext.ActionDescriptor.ControllerDescriptor.ControllerName, 
      filterContext.ActionDescriptor.ActionName, 
      filterContext.HttpContext.Request.UserHostAddress 
     ); 
     var allowExecute = false; 

     if (HttpRuntime.Cache[key] == null) 
     { 
      HttpRuntime.Cache.Add(key, 
       true, 
       null, 
       DateTime.Now.AddSeconds(Seconds), 
       Cache.NoSlidingExpiration, 
       CacheItemPriority.Low, 
       null); 
      allowExecute = true; 
     } 

     if (!allowExecute) 
     { 
      filterContext.Result = new ContentResult 
      { 
       Content = string.Format("You can call this every {0} seconds", Seconds) 
      }; 
      filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Conflict; 
     } 
    } 
} 

E poi decorare l'azione che deve essere limitato:

[RateLimit(Seconds = 10)] 
public ActionResult Index() 
{ 
    return View(); 
} 
+0

Come estendere questo per utilizzare '429 - Too many Requests' secondo [RFC 6586] (http://tools.ietf.org/html/rfc6585) –

+0

@StuartBlacker Suppongo che tu modifichi la seguente riga:' filterContext.HttpContext.Response.StatusCode = (int) HttpStatusCode.Conflict; 'da Conflict a un errore 429. – NicholasFolk

4

Dai un'occhiata alla risposta di Jarrod su come lo fanno su SO.

StackOverflow MVC Throttling

qualche esempio di codice e una spiegazione su come funziona.

+0

Ho un dubbio, e se l'attacco 'DOS' colpisce il server web, allora come mai questa protezione a livello di codice sarà d'aiuto? Non abbiamo bisogno di soluzioni a livello di server Web o di macchina? – stom

+1

@stom - Se l'attacco 'DOS' sta facendo ai tuoi server web, hai già perso una discreta quantità di battaglia. Anche se il server Web lascia semplicemente i pacchetti, l'attacco è fino a quando non si accumula banda e risorse del server per ascoltare, ispezionare e rilasciare i pacchetti. Rate Limiting è più per prevenire gli abusi da un singolo utente o bot, non necessariamente una difesa totale contro gli attacchi 'DOS', anche se può aiutare un po 'nel fatto che non stai eseguendo chiamate/funzioni DB per ogni richiesta come faresti senza alcuna tariffa strozzatura sul posto. – Tommy