api接口访问限制

1.场景描述

     在日常开发接口的时候,尤其是restfull接口,肯定会考虑安全或者是做一些自定义的限制,用来界定并维护代码。那么,我们都会采用什么方法那?通常来讲,我们可以通过session的形式,以访问者的ip为键来记录用户对某接口访问的次数,并对其作出限制。在.net中还可以将session或者是MemoryCache来替换session来实现(另外也可以用第三方nosql:如redis、Mongodb等)。本文结合redis予以实现。

2.实现分析

     通常来说,我们会可以在每一个需要被限制的接口使用redis来存储记录当前来访客户端访问的次数,这样,便可以实现我们想要的效果。但是,少啦可以,如果说,日后很多接口都需要限制该怎么办呐,我们该如何去整理并统筹规划呐?答案就是:可以采用Action过滤器标签的的形式,这样,我们只需封装这样可以限制访问的一个公用的过滤器标签,在需要被限制的地方加上标签,便可以得到我们想要的效果。废话不多说,直接上代码!!!

  1 public class ApiLimitFilter : ActionFilterAttribute
  2     {
  3         #region 可配参数
  4         //标识前缀(唯一)
  5         private string redisKeyPrefix;
  6         public string RedisKeyPrefix
  7         {
  8             get
  9             {
 10                 if (string.IsNullOrEmpty(redisKeyPrefix))
 11                 {
 12                     redisKeyPrefix = "Api_limit";
 13                 }
 14 
 15                 return redisKeyPrefix;
 16             }
 17             set { redisKeyPrefix = value; }
 18         }
 19         //显示时间长度
 20         private TimeSpan? timeSpan { get; set; }
 21         public TimeSpan? TimeSpan
 22         {
 23             get
 24             {
 25                 if (timeSpan == null)
 26                 {
 27                     timeSpan = System.TimeSpan.FromDays(1);
 28                 }
 29                 return timeSpan;
 30             }
 31             set { timeSpan = value; }
 32         }
 33         //显示次数
 34         private int limitCount;
 35         public int LimitCount
 36         {
 37             get
 38             {
 39                 if (limitCount <= 0)
 40                 {
 41                     limitCount = 5;
 42                 }
 43 
 44                 return limitCount;
 45             }
 46             set { limitCount = value; }
 47         }
 48         //提示语
 49         private string notify;
 50         public string Notify
 51         {
 52             get
 53             {
 54                 if (string.IsNullOrEmpty(notify))
 55                 {
 56                     notify = "请求受限";
 57                 }
 58 
 59                 return notify;
 60             }
 61             set { notify = value; }
 62         }
 63         #endregion
 64         #region 内部私用
 65         private string RedisKey
 66         {
 67             get { return string.Format("{0}_{1}", redisKeyPrefix, IpUtil.GetHostAddress()); }
 68         }
 69         private int currentCount = 0;
 70         #endregion
 71         #region Limit
 72         /// <summary>
 73         /// 限制过滤
 74         /// </summary>
 75         /// <param name="actionContext"></param>
 76         public override void OnActionExecuting(HttpActionContext actionContext)
 77         {
 78             //获取接口访问次数(redis封装的工具类/可切换自己想要的东西)
 79             currentCount = RedisCacheHelper.Instance.Get<int>(RedisKey);
 80             if (currentCount > LimitCount)
 81             {
 82                 var resultModel = new ResultModel(200, Notify);
 83                 actionContext.Response=actionContext.Request.CreateResponse(HttpStatusCode.OK, resultModel);
 84              
 85             }
 86             base.OnActionExecuting(actionContext);
 87         }
 88         /// <summary>
 89         /// 限制追记
 90         /// </summary>
 91         /// <param name="actionExecutedContext"></param>
 92         public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
 93         {
 94             currentCount++;
 95             //记住访问痕迹(redis封装的工具类/可切换自己想要的东西)
 96             RedisCacheHelper.Instance.Set(RedisKey, currentCount, TimeSpan);
 97             base.OnActionExecuted(actionExecutedContext);
 98         }
 99         #endregion
100     }
View Code

 

posted @ 2018-12-03 22:01  深海里的一条鱼  阅读(3993)  评论(0编辑  收藏  举报