Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在ASP.NET MVC站点中实现速率限制?_C#_Asp.net_Asp.net Mvc_Limit_Rate Limiting - Fatal编程技术网

C# 如何在ASP.NET MVC站点中实现速率限制?

C# 如何在ASP.NET MVC站点中实现速率限制?,c#,asp.net,asp.net-mvc,limit,rate-limiting,C#,Asp.net,Asp.net Mvc,Limit,Rate Limiting,我正在构建一个ASP.NETMVC站点,我想限制经过身份验证的用户使用该站点某些功能的频率 虽然我从根本上理解了速率限制是如何工作的,但我无法想象如何在不产生主要代码气味的情况下以编程方式实现它 你能告诉我一个简单但功能强大的解决方案来解决这样的问题吗,用C#示例代码 如果重要的话,所有这些函数当前都表示为只接受httppost的操作。我可能最终还想为httpget函数实现速率限制,因此我正在寻找一种适用于所有此类情况的解决方案。如果您使用的是iis7,您可以查看。另一种可能性是将其作为操作过滤

我正在构建一个ASP.NETMVC站点,我想限制经过身份验证的用户使用该站点某些功能的频率

虽然我从根本上理解了速率限制是如何工作的,但我无法想象如何在不产生主要代码气味的情况下以编程方式实现它

你能告诉我一个简单但功能强大的解决方案来解决这样的问题吗,用C#示例代码


如果重要的话,所有这些函数当前都表示为只接受
httppost
的操作。我可能最终还想为
httpget
函数实现速率限制,因此我正在寻找一种适用于所有此类情况的解决方案。

如果您使用的是iis7,您可以查看。另一种可能性是将其作为操作过滤器实施:

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

看看Jarrod关于他们是如何做到这一点的回答


一些示例代码以及对其工作原理的解释。

您如何扩展此代码以使用
429-根据@StuartBlacker,请求过多
,我假设您将编辑以下行:
filterContext.HttpContext.Response.StatusCode=(int)HttpStatusCode.Conflict从冲突到429错误。这里有很好的解决方案。我喜欢它。我要看看我是否能做类似的事情。可能是LRU或滑动窗口超时。这里是另一个完整的教程如何做,它允许更灵活的间隔:我有一个疑问,如果
DOS
攻击击中了web服务器,那么这种代码级保护怎么会有帮助呢?我们不需要web服务器或机器级别的解决方案吗?@stom-如果
DOS
攻击正在对您的web服务器进行攻击,那么您已经输掉了相当多的战斗。即使web服务器只是丢弃数据包,攻击也会占用带宽和服务器资源来侦听、检查和丢弃数据包。速率限制更多的是防止单个用户或机器人滥用,不一定是针对
DOS
攻击的全面防御,尽管它可能会有所帮助,因为您不会像在没有速率限制的情况下那样对每个请求执行DB调用/函数。