翼度科技»论坛 编程开发 .net 查看内容

AspNetCoreRateLimit应用于MVC项目求助

2

主题

2

帖子

6

积分

新手上路

Rank: 1

积分
6
AspNetCoreRateLimit应用于MVC项目求助

前言

之前发过一篇文章:
.NET Core WebApi接口ip限流实践 - 妙妙屋(zy) - 博客园 (cnblogs.com)
然后应用在前后端分离项目这个组件是非常好用的。但应用于不分离的项目,比如我的个人博客就有点麻烦。
就是我的需求是评论接口限流,然后触发限流后要回到文章页面告诉用户你触发了限流,但是,使用这个组件,他会将返回信息以页面的形式返回给你,我并不知道该如何去让他回到文章页面,也是琢磨了很久,用中间件去实现了这个效果,但是感觉不是很理想,如果有大佬知道更好的办法,可以私信或评论,感激不尽。
实现的效果图


评论接口


文章接口


_messages.Warning是博客开源作者封装的提示信息组件,可以采用别的方式去提示,问题不大。这里就是将从缓存中的提示信息提取出来,然后因为这里用的是缓存,用session做的唯一值处理,所以用session去取出来,如果从缓存中查出来存在,则提示被限流。
代码实现

原理就是把组件自带的信息提示设置为空字符串,自己在中间件中去使用。
这是限流规则:

这里参数就不做多的解释,可以去看之前发布的那篇文章。只要把Content设置为空字符串即可。
然后就开始去写中间件去处理触发了限流该怎么做
需要注册缓存服务
builder.Services.AddMemoryCache();
  1. app.Use(async (context, next) =>
  2. {
  3.     var cache = context.RequestServices.GetRequiredService<IMemoryCache>();
  4.    
  5.     // 保存原始响应流
  6.     var originalBody = context.Response.Body;
  7.    
  8.     // 创建一个新的响应流
  9.     using var responseBody = new MemoryStream();
  10.     context.Response.Body = responseBody;
  11.    
  12.     // 加载当前用户的 Session 对象
  13.     await context.Session.LoadAsync();
  14.    
  15.     await next.Invoke();
  16.    
  17.     if (context.Response.StatusCode == 429)
  18.     {
  19.         var referer = context.Request.Headers["Referer"].ToString();
  20.         
  21.         // 从 Session 中获取一个字符串值
  22.         var value = context.Session.GetString("key");
  23.         if (string.IsNullOrEmpty(value))
  24.         {
  25.             // 如果 Session 中没有值,则设置一个字符串值
  26.             context.Session.SetString("key", "value");
  27.         }
  28.         var sessionId = context.Session.Id;
  29.         if (!cache.TryGetValue("Errors", out Dictionary<string, string> errors))
  30.         {
  31.             errors = new Dictionary<string, string>();
  32.             cache.Set("Errors", errors, TimeSpan.FromSeconds(10));
  33.         }
  34.         
  35.         errors[sessionId] = "您的请求已被限流,请稍后再试。";
  36.         
  37.         // 重置响应流位置
  38.         responseBody.Seek(0, SeekOrigin.Begin);
  39.         
  40.         // 读取响应内容
  41.         // var bodyText = new StreamReader(responseBody).ReadToEnd();
  42.         
  43.         // 设置新的响应流
  44.         context.Response.Body = originalBody;
  45.         
  46.         // 设置新的响应状态码
  47.         context.Response.StatusCode = 302;
  48.         context.Response.Headers["Location"] = referer;
  49.         
  50.     }
  51.     else
  52.     {
  53.         // 将响应流写回到原始响应流中
  54.         responseBody.Seek(0, SeekOrigin.Begin);
  55.         await responseBody.CopyToAsync(originalBody);
  56.         
  57.     }
  58. });
复制代码
注意这个中间件处理要放在app.UseRateLimit();前面。
结尾

AspNetCoreRateLimit原本就讲限流的ip存放在redis当中了的,但是我就是查不出来,如果能用该组件自带的方法查询出来,就不需要再写一个中间件,当429的时候再用缓存存一次会话了。
总之暂且先用这种办法吧,如果有更好的方法可以评论哟~

来源:https://www.cnblogs.com/ZYPLJ/archive/2023/05/07/17380401.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具