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();
}
}
}