ASP.NET WebApi实现请求频率限制

SampleController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web; using System.Web.Http; namespace App.Controllers { [Throttle] public class SampleController : ApiController { [HttpGet] public async Task<IHttpActionResult> Get() => await Task.FromResult(Ok(Guid.NewGuid().ToString())); } }

ThrottleAttribute.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http; using System.Threading; using System.Threading.Tasks; using System.Web; using System.Web.Http.Controllers; using System.Web.Http.Filters; namespace App { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class ThrottleAttribute : ActionFilterAttribute { private readonly HandleRequest _handleRequest; public ThrottleAttribute() { this._handleRequest = new HandleRequest(); } public override async Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken) { var valid = await this._handleRequest.IsValidRequest(actionContext.Request); if (!valid) { actionContext.Response = new HttpResponseMessage((HttpStatusCode)429) { ReasonPhrase = "Too Many Requests!" }; } } } }

HandleRequest.cs

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net.Http; using System.ServiceModel.Channels; using System.Threading.Tasks; using System.Web; using System.Web.Caching; namespace App { public class HandleRequest { private string Name { get; } = "Client1"; private int Seconds { get; } = int.Parse(ConfigurationManager.AppSettings.Get("waitMillisecond")); public async Task<bool> IsValidRequest(HttpRequestMessage requestMessage) { var allowExecute = false; await Task.Factory.StartNew(() => { var key = string.Concat(Name, "-", GetClientIp(requestMessage)); if (HttpRuntime.Cache[key] == null) { HttpRuntime.Cache.Add(key, true, //这是我们可以拥有的最小数据吗? null, // 没有依赖关系 DateTime.Now.AddMilliseconds(Seconds), // 绝对过期 Cache.NoSlidingExpiration, CacheItemPriority.Low, null); //没有回调 allowExecute = true; } }); return allowExecute; } private string GetClientIp(HttpRequestMessage request) { //获取传统context if (request.Properties.ContainsKey("MS_HttpContext")) { //HttpContextWrapper 类是从 HttpContextBase 类派生的。 HttpContextWrapper 类用作 HttpContext 类的包装。 在运行时,通常使用 HttpContextWrapper 类的实例调用 HttpContext 对象上的成员。 return ((HttpContextWrapper)request.Properties["MS_HttpContext"]).Request.UserHostAddress; } //CS客户端获取ip地址 //让与发送消息的远程终结点有关的客户端 IP 地址和端口号可用。 if (request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name)) { RemoteEndpointMessageProperty prop; prop = (RemoteEndpointMessageProperty)request.Properties[RemoteEndpointMessageProperty.Name]; return prop.Address; } return null; } } }

运行结果:

这里写图片描述

1分钟内,连续请求的结果:

这里写图片描述

猜你喜欢

转载自www.cnblogs.com/hnsongbiao/p/9376116.html
今日推荐