写点什么

简单的限流过滤器

  • 2024-06-13
    福建
  • 本文字数:2930 字

    阅读完需:约 10 分钟

API 接口都是提供给第三方服务/客户端调用,所有请求地址以及请求参数都是暴露给用户的。


每次请求一个 HTTP 请求,用户都可以通过 F12,或者抓包工具看到请求的 URL 链接,然后 copy 出来。这样是非常不安全的,有人可能会恶意的刷我们的接口,那这时该怎么办呢?


增加一个全局过滤器 获取客户端的 IP  限制固定时间内的访问次数即可


第一步:创建全局过滤器 RateLimitFilter

public class RateLimitFilter : ActionFilterAttribute    {        private const int MaxRequests = 30; //1分钟访问最大频率        private bool StartUp = true; //是否启用        public override void OnActionExecuting(ActionExecutingContext context)        {            if (StartUp)            {                base.OnActionExecuting(context);                string clientId = GetIP();                if (GetCache(clientId) == null)                {                    SetCacheRelativeTime(clientId, 1, 60);                }                else                {                    var cs = int.Parse(GetCache(clientId).ToString());                    SetCacheRelativeTime(clientId, cs += 1, 60);                }                //var x = int.Parse(GetCache(clientId).ToString());                if (int.Parse(GetCache(clientId).ToString()) > MaxRequests)                {                    //返回值规范不统一                    context.Result = new ContentResult { Content = "<script type='text/javascript'>alert('" + clientId + "  访问过于频繁,请稍等片刻!');</script><h1 style='text-align: center; color: red;'>" + clientId + "  访问过于频繁,请稍等片刻!<h1>" };
//返回值规范统一 前端有错误提示 //context.Result = new JsonResult() //{ // Data = new { Result = false, status = false, suc = false, message = "" + clientId + " 访问过于频繁,请稍等片刻!" }, // JsonRequestBehavior = JsonRequestBehavior.AllowGet //}; } } }

/// <summary> /// 获取客户端IP地址 /// </summary> /// <returns>若失败则返回回送地址</returns> public static string GetIP() { //如果客户端使用了代理服务器,则利用HTTP_X_FORWARDED_FOR找到客户端IP地址 string userHostAddress = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; if (!string.IsNullOrEmpty(userHostAddress)) { userHostAddress = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString().Split(',')[0].Trim(); } //否则直接读取REMOTE_ADDR获取客户端IP地址 if (string.IsNullOrEmpty(userHostAddress)) { userHostAddress = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]; } //前两者均失败,则利用Request.UserHostAddress属性获取IP地址,但此时无法确定该IP是客户端IP还是代理IP if (string.IsNullOrEmpty(userHostAddress)) { userHostAddress = HttpContext.Current.Request.UserHostAddress; } //最后判断获取是否成功,并检查IP地址的格式(检查其格式非常重要) if (!string.IsNullOrEmpty(userHostAddress) && IsIP(userHostAddress)) { return userHostAddress; } return "127.0.0.1"; }
/// <summary> /// 检查IP地址格式 /// </summary> /// <param name="ip"></param> /// <returns></returns> public static bool IsIP(string ip) { return System.Text.RegularExpressions.Regex.IsMatch(ip, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$"); }
#region 设置相对过期时间Cache值(即:访问激活后不过期) /// <summary> /// 设置相对过期时间Cache值(即:访问激活后不过期) /// </summary> /// <param name="objectkey"></param> /// <param name="objObject"></param> /// <param name="timeSpan">超过多少时间不调用就失效,单位是秒</param>
public static void SetCacheRelativeTime(string objectkey, object objObject, int timeSpan) { System.Web.Caching.Cache objCache = HttpRuntime.Cache; objCache.Insert(objectkey, objObject, null, DateTime.MaxValue, TimeSpan.FromSeconds(timeSpan)); } #endregion
#region 获取当前应用程序指定CacheKey的Cache值 /// <summary> /// 获取当前应用程序指定CacheKey的Cache值 /// </summary> /// <param name="CacheKey"></param> /// <returns></returns>y public static object GetCache(string CacheKey) { try { System.Web.Caching.Cache objCache = HttpRuntime.Cache; Object value = objCache[CacheKey]; if (value != null) { return value; } else { return null; } } catch (Exception) { return null; }
} #endregion }
复制代码


第二步:FilterConfig类并注册你的全局过滤器

public class FilterConfig {        public static void RegisterGlobalFilters(GlobalFilterCollection filters)        {            filters.Add(new RateLimitFilter()); // 过滤器        } }
复制代码


第三步:Global.asax 文件中注册全局过滤器

protected void Application_Start(){            AreaRegistration.RegisterAllAreas();            RouteConfig.RegisterRoutes(RouteTable.Routes);            BundleConfig.RegisterBundles(BundleTable.Bundles);            UnityConfig.RegisterComponents();
// 注册全局过滤器 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
}
复制代码


文章转载自:风中起舞

原文链接:https://www.cnblogs.com/zj19940610/p/18244414

体验地址:http://www.jnpfsoft.com/?from=infoq

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
简单的限流过滤器_不在线第一只蜗牛_InfoQ写作社区