如何在Web Api中限制请求?

 周鑫先生_852 发布于 2023-02-07 17:53

我正在尝试通过以下方式实现请求限制:

在ASP.NET MVC中实现请求限制的最佳方法?

我已将该代码提取到我的解决方案中,并使用以下属性修饰了API控制器端点:

[Route("api/dothis/{id}")]
[AcceptVerbs("POST")]
[Throttle(Name = "TestThrottle", Message = "You must wait {n} seconds before accessing this url again.", Seconds = 5)]
[Authorize]
public HttpResponseMessage DoThis(int id) {...}

这会编译,但属性的代码不会被命中,并且限制不起作用.我没有收到任何错误.我错过了什么?

3 个回答
  • 建议的解决方案不准确.至少有5个理由.

      缓存不提供不同线程之间的互锁控制,因此可以同时处理多个请求,从而引入跳过限制的额外调用.

      过滤器正在Web API管道中"在游戏中太晚"处理,因此在您决定不应该处理请求之前,需要花费大量资源.应该使用DelegatingHandler,因为它可以设置为在Web API管道的开头运行,并在执行任何其他工作之前切断请求.

      Http缓存本身是新的运行时可能无法使用的依赖项,例如自托管选项.最好避免这种依赖.

      上述示例中的缓存不保证其在调用之间的存活,因为它可能由于内存压力而被移除,尤其是低优先级.

      虽然问题不是太糟糕,但将响应状态设置为"冲突"似乎并不是最佳选择.最好使用'429-too many requests'来代替.

    在实施限制时,还有许多问题和隐藏的障碍需要解决.有免费的开源选项.我建议您查看https://throttlewebapi.codeplex.com/.

    2023-02-07 17:55 回答
  • WebApiThrottle现在已成为该领域的冠军.

    它非常容易集成.只需将以下内容添加到App_Start\WebApiConfig.cs:

    config.MessageHandlers.Add(new ThrottlingHandler()
    {
        // Generic rate limit applied to ALL APIs
        Policy = new ThrottlePolicy(perSecond: 1, perMinute: 20, perHour: 200)
        {
            IpThrottling = true,
            ClientThrottling = true,
            EndpointThrottling = true,
            EndpointRules = new Dictionary<string, RateLimits>
            { 
                 //Fine tune throttling per specific API here
                { "api/search", new RateLimits { PerSecond = 10, PerMinute = 100, PerHour = 1000 } }
            }
        },
        Repository = new CacheRepository()
    });
    

    它也可以作为一个同名的nuget使用.

    2023-02-07 17:55 回答
  • 您似乎混淆了ASP.NET MVC控制器的动作过滤器和ASP.NET Web API控制器的动作过滤器.这是两个完全不同的类:

    对于ASP.NET MVC:System.Web.Mvc.ActionFilterAttribute- >这就是你从链接中得到的

    对于ASP.NET Web API:System.Web.Http.Filters.ActionFilterAttribute- >这就是您需要实现的

    看来,您所显示的是Web API控制器操作(在控制器内部声明的操作ApiController).因此,如果您要对其应用自定义过滤器,则必须从中派生System.Web.Http.Filters.ActionFilterAttribute.

    那么让我们继续并调整Web API的代码:

    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(HttpActionContext actionContext)
        {
            var key = string.Concat(Name, "-", GetClientIp(actionContext.Request));
            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.";
                }
    
                actionContext.Response = actionContext.Request.CreateResponse(
                    HttpStatusCode.Conflict, 
                    Message.Replace("{n}", Seconds.ToString())
                );
            }
        }
    }
    

    其中GetClientIp方法来自this post.

    现在,您可以在Web API控制器操作上使用此属性.

    2023-02-07 17:55 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有