我最近一直在使用 Ocelot 构建 API 网关。速率限制是否基于请求者客户端 ID?因为我被要求在一个看起来像这样的架构中构建一个 api 网关
所有请求都将具有相同的 id,因为它们是通过代理传递的。 但是,我可以使用标头令牌来识别不同的请求客户端。所以我的问题是:我可以使用标头令牌而不是请求 ID 来限制客户端发出的请求数量吗?预先感谢。
您可以使用 Ocelot 作为基于 ClientId 的速率限制器。
"RateLimitOptions": {
"DisableRateLimitHeaders": false,
"QuotaExceededMessage": "Customize Tips!",
"HttpStatusCode": 999,
"ClientIdHeader" : "MY-CLIENT-ID"
}
Ocelot 的速率限制文档中的最后一行指的是:
您还可以实现自己的中间件并使用 Ocelots 速率限制。这样您就可以读取其他标头并获取您的自定义客户端 ID:ClientIdHeader - 允许您指定用于识别客户端的标头。默认是“ClientId”
看一下Ocelot提供的默认限速中间件:
public virtual ClientRequestIdentity SetIdentity(HttpContext httpContext, RateLimitOptions option)
{
var clientId = "client";
if (httpContext.Request.Headers.Keys.Contains(option.ClientIdHeader))
{
clientId = httpContext.Request.Headers[option.ClientIdHeader].First();
}
return new ClientRequestIdentity(
clientId,
httpContext.Request.Path.ToString().ToLowerInvariant(),
httpContext.Request.Method.ToLowerInvariant()
);
}
// Authentication
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.Authority = builder.Configuration.GetSection("OAuthSettings:Authority").Get<string>();
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidAudiences = builder.Configuration.GetSection("OAuthSettings:Audiences").Get<string>().Split(';')
};
options.RequireHttpsMetadata = false;
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
return Task.CompletedTask;
},
OnTokenValidated = context =>
{
// Adding the ClientId in the header
// It is used by the rate limiting
string clientId = context.Principal.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.ClientId).Value;
context.HttpContext.Request.Headers.Add("ClientId", clientId);
return Task.CompletedTask;
},
};
});
{
"Routes": [
{
"DownstreamPathTemplate": "/weatherforecast",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 7094
}
],
"UpstreamPathTemplate": "/gatewaycheck",
"UpstreamHttpMethod": [ "Get" ],
"UpstreamHeaderTransform": {
"ClientId": "MyClient"
},
"RateLimitOptions": {
"ClientWhitelist": [ "MyClient" ],
"EnableRateLimiting": true,
"Period": "15s",
"PeriodTimespan": 1,
"Limit": 1
}
}
]
}
试试这个!!!!