.NET Core接口限流:如何根据剩余配额展示前端提示信息
解决方案
要实现根据剩余请求配额展示不同提示,核心是让后端在每次响应中返回剩余的请求许可数,前端读取该值后进行判断。以下是具体步骤:
1. 后端修改:添加剩余配额到响应头
更新限流配置与响应处理
修改Program.cs的限流设置,在被拒绝请求和正常请求中都返回剩余许可数的自定义响应头,同时配置CORS允许前端读取这些头:
builder.Services.AddRateLimiter(options => { options.AddPolicy("forgotPassword", context => RateLimitPartition.GetFixedWindowLimiter( partitionKey: context.Connection.RemoteIpAddress, factory: partition => new FixedWindowRateLimiterOptions { AutoReplenishment = true, PermitLimit = 3, Window = TimeSpan.FromMinutes(1) })); options.OnRejected = async (context, token) => { context.HttpContext.Response.StatusCode = 429; // 给拒绝请求添加剩余配额头 if (context.Lease.TryGetMetadata(MetadataName.RateLimitRemaining, out var remaining)) { context.HttpContext.Response.Headers.Add("X-RateLimit-Remaining", remaining.ToString()); } await context.HttpContext.Response.WriteAsync("Too many requests. Please try later again... ", cancellationToken: token); }; }); // 配置CORS,暴露自定义响应头 builder.Services.AddCors(options => { options.AddPolicy("AllowAngular", policy => { policy.WithOrigins("你的Angular前端地址") .AllowAnyHeader() .AllowAnyMethod() .ExposeHeaders("X-RateLimit-Remaining"); }); }); app.UseCors("AllowAngular");
控制器中添加正常响应的配额头
在ForgotPassword方法中,获取当前请求的限流租赁信息,添加剩余配额到响应头:
[EnableRateLimiting("forgotPassword")] [AllowAnonymous] [HttpPost] public async Task<IActionResult> ForgotPassword(string email) { var result = await userService.ForgotPassword(email); // 获取限流租赁信息并添加响应头 if (HttpContext.GetMetadata<RateLimitLease>() is { } lease) { if (lease.TryGetMetadata(MetadataName.RateLimitRemaining, out var remaining)) { Response.Headers.Add("X-RateLimit-Remaining", remaining.ToString()); } } return Ok(result); }
2. 前端Angular修改:读取响应头并展示对应提示
首先确保API服务返回完整的响应对象(包含headers),修改apiService的请求方法:
fPassword(email: string): Observable<HttpResponse<any>> { return this.http.post<any>('/api/account/ForgotPassword', { email }, { observe: 'response' }); }
然后修改订阅逻辑,根据剩余配额显示不同提示:
this.apiService .fPassword(email) .pipe(take(1)) .subscribe({ next: (res) => { const remainingStr = res.headers.get('X-RateLimit-Remaining'); if (remainingStr) { const remainingCount = parseInt(remainingStr, 10); if (remainingCount === 2) { this.message('验证码发送成功,你还有2次请求机会'); } else if (remainingCount === 1) { this.message('验证码发送成功,你还有1次请求机会'); } else { this.message('验证码发送成功'); } } else { this.message('验证码发送成功'); } }, error: (error) => { if(error.status === 429){ this.message('请求次数过多,请稍后再试'); } else { this.message('发送失败,请重试'); } } });
内容的提问来源于stack exchange,提问作者Nic
相关产品推荐
相关产品推荐

