using EzCoreNet.Redis; using Furion; using Furion.FriendlyException; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Claims; using System.Text; using System.Threading.Tasks; namespace Cylsg.Filter { public enum Limttype { /// ///共用限流 /// All, /// /// 用户级限流 /// User } /// /// 限流 /// public class LimitFilterAttribute : Attribute,IAsyncActionFilter { /// /// redis限流文件夹名称 /// private const string DirKey = "UserRateLimit:"; /// /// 限流发生时 返回的提示 /// public string ResponseMeg { get; set; } = "请不要在短时间内重复访问该资源"; /// /// 限流时长 单位秒 默认为1秒 /// public int timespan { get; set; } = 1; /// /// 限流次数 默认为1次 /// public int InCount { get; set; } = 1; /// /// 默认为用户级 /// public Limttype LimiType { get; set; }= Limttype.All; public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { var redisHelper = App.GetService(); if(redisHelper == null) { throw Oops.Oh("内存服务异常,请求终止"); } var path = context.HttpContext?.Request?.Path.Value; if (string.IsNullOrEmpty(path)) { //非API控制器,直接放行 没有找到路径 await next.Invoke(); return; } string key = ""; if (LimiType == Limttype.User) { if (App.User?.FindFirstValue("UserID") == null) { //没有用户直接放行 await next.Invoke(); return; } key = $"{DirKey}:{path}:{App.User?.FindFirstValue("UserID")}"; } else if(LimiType == Limttype.All) { key = $"{DirKey}:{path}:All"; } else { await next.Invoke(); return; } long? count = redisHelper.Get(key); if (count == null || count == 0) { redisHelper.Incrby(key); redisHelper.SetTtl(key, timespan); } else if (count >= (InCount)) { throw Oops.Oh(ResponseMeg); } else { redisHelper.Incrby(key); } await next.Invoke(); } } }