在平常開發接口的時候,尤爲是restfull接口,確定會考慮安全或者是作一些自定義的限制,用來界定並維護代碼。那麼,咱們都會採用什麼方法那?一般來說,咱們能夠經過session的形式,以訪問者的ip爲鍵來記錄用戶對某接口訪問的次數,並對其做出限制。在.net中還能夠將session或者是MemoryCache來替換session來實現(另外也能夠用第三方nosql:如redis、Mongodb等)。本文結合redis予以實現。redis
一般來講,咱們會能夠在每個須要被限制的接口使用redis來存儲記錄當前來訪客戶端訪問的次數,這樣,即可以實現咱們想要的效果。可是,少啦能夠,若是說,往後不少接口都須要限制該怎麼辦吶,咱們該如何去整理並統籌規劃吶?答案就是:能夠採用Action過濾器標籤的的形式,這樣,咱們只需封裝這樣能夠限制訪問的一個公用的過濾器標籤,在須要被限制的地方加上標籤,即可以獲得咱們想要的效果。廢話很少說,直接上代碼!!!sql
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 }