我正在构建一个 ASP.NET MVC 站点,我想在其中限制经过身份验证的用户可以使用该站点的某些功能的频率。
尽管我从根本上了解速率限制的工作原理,但我无法想象如何以编程方式实现它而不产生主要的代码异味。
您能否通过 C# 示例代码向我指出一个简单而强大的解决方案来解决此类问题?
如果重要的话,所有这些功能目前都表示为只接受的动作HTTP POST
。我最终可能还想对HTTP GET
函数实施速率限制,因此我正在寻找一种适用于所有此类情况的解决方案。
我正在构建一个 ASP.NET MVC 站点,我想在其中限制经过身份验证的用户可以使用该站点的某些功能的频率。
尽管我从根本上了解速率限制的工作原理,但我无法想象如何以编程方式实现它而不产生主要的代码异味。
您能否通过 C# 示例代码向我指出一个简单而强大的解决方案来解决此类问题?
如果重要的话,所有这些功能目前都表示为只接受的动作HTTP POST
。我最终可能还想对HTTP GET
函数实施速率限制,因此我正在寻找一种适用于所有此类情况的解决方案。
如果您使用的是 IIS 7,您可以查看Dynamic IP Restrictions Extension。另一种可能性是将其实现为动作过滤器:
[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;
}
}
}
然后装饰需要限制的动作:
[RateLimit(Seconds = 10)]
public ActionResult Index()
{
return View();
}