2010-06-21 9 views
9

Buduję witrynę ASP.NET MVC, w której chcę ograniczyć częstotliwość, z jaką użytkownicy uwierzytelnieni mogą korzystać z niektórych funkcji witryny.Jak wdrożyć ograniczenie szybkości w witrynie ASP.NET MVC?

Chociaż rozumiem, jak zasadniczo działa ograniczenie szybkości, nie mogę sobie wyobrazić, jak zaimplementować programowo, bez tworzenia poważnego zapachu kodu.

Czy mogę wskazać mi proste, ale potężne rozwiązanie dla rozwiązania tego problemu, z kodu próbki C#?

Jeśli to ma znaczenie, wszystkie te funkcje są obecnie wyrażane jako Działania, które akceptują tylko HTTP POST. Mogę ewentualnie chcieć implementować ograniczenia prędkości również dla funkcji HTTP GET, więc szukam rozwiązania, które działa na wszystkie takie okoliczności.

+0

Oto kolejny kompletny samouczek, jak to zrobić, co pozwala na bardziej elastyczne interwały: https://www.shieldui.com/blogs/rate-limiting-in-asp-net-mvc –

Odpowiedz

15

Jeśli korzystasz z IIS 7, możesz rzucić okiem na Dynamic IP Restrictions Extension. Inną możliwością jest wprowadzenie tego jako filtr Działanie:

[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; 
     } 
    } 
} 

A potem ozdobić działania, które muszą być ograniczone:

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

Jak można rozszerzyć to do wykorzystania '429 - Too Many Requests' zgodnie z [RFC 6586] (http://tools.ietf.org/html/rfc6585) –

+0

@StuartBlacker Zakładam, że edytowałbyś następujący wiersz:' filterContext.HttpContext.Response.StatusCode = (int) HttpStatusCode.Conflict; 'from Conflict do błędu 429. – NicholasFolk

4

spojrzeć na odpowiedź Jarrod na temat tego jak robią to na SO.

StackOverflow MVC Throttling

Niektóre przykładowy kod jak również wyjaśnienie, w jaki sposób to działa.

+0

Mam wątpliwości, co się stanie, jeśli atak "DOS" trafi na serwer WWW, dlaczego ochrona tego kodu pomoże? Czy nie potrzebujemy rozwiązania na poziomie serwera lub maszyny? – stom

+1

@stom - Jeśli atak na "DOS" trafia na twoje serwery, straciłeś już przyzwoitą ilość bitwy. Nawet jeśli serwer sieciowy po prostu przerywa pakiety, atak trwa do momentu przywiązania przepustowości i zasobów serwera, aby przesłuchać, sprawdzić i upuścić pakiet (y). Ograniczanie stawek jest bardziej w celu zapobiegania nadużyciom ze strony pojedynczego użytkownika lub botów, niekoniecznie jest to całkowita obrona przed atakami typu "DOS", chociaż może pomóc nieco w tym, że nie wykonujesz wywołań/funkcji DB dla każdego żądania, tak jak byś bez stopy dławienie w miejscu. – Tommy

Powiązane problemy