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)
{
//返回值規(guī)范不統(tǒng)一
context.Result = new ContentResult { Content = "<script type='text/javascript'>alert('" + clientId + " 訪問過于頻繁,請稍等片刻!');</script><h1 style='text-align: center; color: red;'>" + clientId + " 訪問過于頻繁,請稍等片刻!<h1>" };
//返回值規(guī)范統(tǒng)一 前端有錯誤提示
//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()
{
//如果客戶端使用了代理服務(wù)器,則利用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 設(shè)置相對過期時間Cache值(即:訪問激活后不過期)
/// <summary>
/// 設(shè)置相對過期時間Cache值(即:訪問激活后不過期)
/// </summary>
/// <param name="objectkey"></param>
/// <param name="objObject"></param>
/// <param name="timeSpan">超過多少時間不調(diào)用就失效,單位是秒</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 獲取當(dāng)前應(yīng)用程序指定CacheKey的Cache值
/// <summary>
/// 獲取當(dāng)前應(yīng)用程序指定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
}