您的位置:首页 > 编程语言 > ASP

.NetCore——AspNetCoreRateLimit简单使用

2020-01-13 04:19 239 查看

.NetCore——AspNetCoreRateLimit简单使用

一、介绍

在做项目的时候给到需求对接口进行限流,防止恶意刷接口。在网上找了资料使用了AspNetCoreRateLimit限流中间件,在这我分享一下我的一些 总结与解读 。。。。 接下来我们就开启限流之路

二、安装

我们先安装AspNetCoreRateLimit
在NuGet或 Install-Package AspNetCoreRateLimit 命令安装

三、配置

先注册服务

public void ConfigureServices(IServiceCollection services)
{
// needed to load configuration from appsettings.json
services.AddOptions();

// needed to store rate limit counters and ip rules
services.AddMemoryCache();

//load general configuration from appsettings.json
services.Configure<IpRateLimitOptions>(Configuration.GetSection("IpRateLimiting"));

//load ip rules from appsettings.json
services.Configure<IpRateLimitPolicies>(Configuration.GetSection("IpRateLimitPolicies"));

// inject counter and rules stores
services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();
services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();

// Add framework services.
services.AddMvc();

// https://github.com/aspnet/Hosting/issues/793
// the IHttpContextAccessor service is not registered by default.
// the clientId/clientIp resolvers use it.
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

// configuration (resolvers, counter key builders)
services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
}

在官方文档中写的是要先注册这个中间件然后在注册其他的组件。

注册服务的时候,一定要有下面这两个否则会不生效
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();

然后在添加中间件

在此处这个 app.UseIpRateLimiting(); 一定要放在mvc的前边 不然的话 不会生效的。 此处由于我自己 重写了插件本身的一些方法,所以此处是 app.UseMiddleware<IP.CustomizationLimitMiddleware>().UseIpRateLimiting(); 这样的,如果重写的类(CustomizationLimitMiddleware)不放在这里 重写的也是不会生效的

这些配置好以后呢 开始配置限制规范

"IpRateLimiting": {
"EnableEndpointRateLimiting": true,
"StackBlockedRequests": false,
"RealIpHeader": "X-Real-IP",
"ClientIdHeader": "X-ClientId",
"IpWhitelist": null,
"EndpointWhitelist": null,
"HttpStatusCode": 429,
"QuotaExceededResponse": {
"Content": "{{ \"message\": \"Too many requests,Please try again in {2} second(s).\", \"code\": 429,\"data \":\"\"}}",
"ContentType": "application/json"
},
"GeneralRules": [
{
"Endpoint": "*",
"Period": "1s",
"Limit": 1
}
]
},

在appsettings.json文件里面填入这段代码
此处的IpRateLimiting节点是注册服务里面读取的IpRateLimiting

下面咱们开始了解一下里面的参数吧
EnableEndpointRateLimiting:当为True的时候 例如设置了5次每分钟访问限流,当你getData()5次过后禁止访问,但是还可以访问postData()5次,总得来说是每个接口都有5次在这一分钟,互不干扰。
当为False的时候 每个接口都加入计数,不管你访问哪个接口 只要在一分钟内累计够5次 将禁止访问

StackBlockedRequests:设置为false,则拒绝的呼叫不会添加到油门计数器。如果客户每秒发出3个请求,而您设置的限制为每秒一个呼叫,则其他限制(例如每分钟或每天)将仅记录第一个呼叫,而该呼叫未被阻止。如果您希望被拒绝的请求计入其他限制,则必须设置StackBlockedRequests为true

RealIpHeader:使用时,你的红隼服务器背后是一个反向代理,如果你的代理服务器使用不同的页眉然后提取客户端IP X-Real-IP使用此选项来设置它

ClientIdHeader :被用于提取白名单的客户端ID。如果此标头中存在客户端ID,并且与ClientWhitelist中指定的值匹配,则不应用速率限制

  • 这里 ClientIdHeader的ID限制 跟 IP限制都是一样的 细节处有些许不同
services.Configure<ClientRateLimitOptions>(Configuration.GetSection("ClientRateLimiting"));

//load client rules from appsettings.json
services.Configure<ClientRateLimitPolicies>(Configuration.GetSection("ClientRateLimitPolicies"));
  • IP注册服务的时候是 IpRateLimiting 和 IpRateLimitPolicies ,现在ID注册服务替换成 ClientRateLimiting 和 ClientRateLimitPolicies
  • RateLimiting 结尾的节点是用来初始化自定义的一些设置
  • RateLimitPolicies 结尾的节点是用来单独定义白名单里面的 覆盖特定客户

IpWhitelistClientWhitelist 这两个都是用来设置白名单的 区别在与前者通过IP设置 后者通过请求ID设置

"IpWhitelist": [ "::1","::10" ],
"ClientWhitelist ":[" dev-id-1 ", "dev-id-2 " ],

HttpStatusCode:用来设置返回状态码
QuotaExceededResponse:设置返回提示信息
GeneralRules:在这里设置你的限制条件,可以设置多种条件,可以针对IP、接口

下面这个是全部 每秒最多访问一次

{
"Endpoint": "*",//端点
"Period": "1s",//周期 s秒 m分钟 h时 d天
"Limit": 1  //次数
}

还有具体到控制器、方法、请求方式 下面依次贴几个例子
控制:

{
"Endpoint":"*:api/values",
"Period":"1s",
"Limit":1
}

Endpoint 现在的值 values控制器里面的所有方法

"get:api/values"   //values控制器下所有的Get请求  get改成post的话就是所有的Post请求

我在控制器里面 改的路由是这样的

我自己测试的时候这个没法具体到控制器与哪种请求 只能具体到方法 应该是我后边设置了/[action]的问题

在开发中的时候一定要注意这里!!!

下面是ID的设置方式

{
"ClientId": "client-id-1",
"Rules": [
{
"Endpoint": "*",
"Period": "1s",
"Limit": 10
},
{
"Endpoint": "*",
"Period": "15m",
"Limit": 200
}
]
},

根据自己的需求设置了 这些以后就Ok了!

四、扩展

在注册服务的时候可以这样写 把读取appsetting.json文件中的 IpRateLimiting 节点替换,然后这样写。
以 RateLimitPolicies 结尾的 IP 和 ID 的节点这样写也是可以的

后台方法重写

这个Class是用于重写的插件本身的一些方法,在上边添加中间件的时候,简单的有提过。因为我在项目开发的时候 需要将请求频繁的IP存储到数据库进行记录,所以我用到了 ReturnQuotaExceededResponse() 这个方法, 只要插件识别到 请求过于频繁就会走这个方法。

在这个方法中可以定义返回的信息,在这里设置过后 会替换掉初始的时候设置的值,也可以在这个方法里得到请求过于频繁的IP。

ResolveIdentity() 这个看的文档说是可以自定义拦截逻辑的 我也没有用到 就重写了一下试试 。
这里面还有记录Log的方法可以重写

注意!坑!!!

你在官方文档复制了这个class里面的code会报错

现在贴出我写的,改了点东西,已经不报错,而且暂时还没有问题

public class CustomizationLimitMiddleware : IpRateLimitMiddleware
{
private readonly IpRateLimitOptions _options;
private readonly IIpPolicyStore _ipPolicyStore;

public CustomizationLimitMiddleware(RequestDelegate next, IOptions<IpRateLimitOptions> options, IRateLimitCounterStore counterStore, IIpPolicyStore policyStore, IRateLimitConfiguration config, ILogger<IpRateLimitMiddleware> logger, IIpAddressParser ipParser = null) : base(next, options, counterStore, policyStore, config, logger)
{
_options = options.Value;
_ipPolicyStore = policyStore;
}
/// <summary>
///重写的此方法 可以自定义逻辑 暂时搁置
/// </summary>
/// <param name="httpContext"></param>
/// <returns></returns>
public override ClientRequestIdentity ResolveIdentity(HttpContext httpContext)
{
var clientId = "anon";
if (httpContext.Request.Headers.Keys.Contains(_options.ClientIdHeader, StringComparer.CurrentCultureIgnoreCase))
{
clientId = httpContext.Request.Headers[_options.ClientIdHeader].First();
}

return new ClientRequestIdentity
{
Path = httpContext.Request.Path.ToString().ToLowerInvariant(),
HttpVerb = httpContext.Request.Method.ToLowerInvariant(),
ClientId = clientId
};
}

/// <summary>
/// 当请求过于频繁时 接口重写
/// </summary>
/// <param name="httpContext"></param>
/// <param name="rule"></param>
/// <param name="retryAfter"></param>
/// <returns></returns>
public override Task ReturnQuotaExceededResponse(HttpContext httpContext, RateLimitRule rule, string retryAfter)
{
var message = string.Format("{{ \"message\": \"请求过于频繁,请在{2}秒后在重新尝试.\", \"code\": 429,\"data \":\"\"}}", rule.Limit, rule.Period, retryAfter);

if (!_options.DisableRateLimitHeaders)
{
httpContext.Response.Headers["Retry-After"] = retryAfter;
}

httpContext.Response.StatusCode = _options.QuotaExceededResponse?.StatusCode ?? _options.HttpStatusCode;
httpContext.Response.ContentType = _options.QuotaExceededResponse?.ContentType ?? "text/plain";

return httpContext.Response.WriteAsync(message);
}
}

插件开发者Demo、文档直通车: 请坐好,即将起飞

好了!就到此结束了!

希望在这条不归路上,越走越远!

  • 点赞 1
  • 收藏
  • 分享
  • 文章举报
小学生—乔凡 发布了7 篇原创文章 · 获赞 1 · 访问量 205 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: