public async Task <LimitRequestBannedData> CheckForBanAndIncreaseRequestsCount( string ip, int requestsPerTime, TimeSpan time, TimeSpan banTime, string controllerName, string actionName, string methodType, bool uniqueForEveryActionAndController = true, bool useTestMode = false) { if (useTestMode) { ip = $"101.TEST.MODE.101"; } if (uniqueForEveryActionAndController) { ip = GenerateUniquePathKeyIp(methodType, ip, controllerName, actionName); } else { ip = "LimitRequestsCounter:" + ip; } await UpdateValidToTime(ip, time); LimitRequestBannedData isBannedData = await IsBannedAsync(ip); bool isBanned = isBannedData.IsBanned; if (isBanned) { return(isBannedData); } else { await SetIpRequestsCountAsync(ip, time); if (await GetIpRequestCountAsync(ip) >= requestsPerTime) { await BanIpRequestsAsync(ip.ToString(), banTime); } return(isBannedData); } }
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { var limitRequestsService = context.HttpContext.RequestServices.GetRequiredService <ILimitRequestsService>(); var ip = context.HttpContext.Connection.RemoteIpAddress?.ToString(); if (ip == null && useTestMode == false) { //TODO: Think what to do if we don't have the IP in the request. await next(); return; } string controllerName = context.RouteData.Values["controller"].ToString(); string actionName = context.RouteData.Values["action"].ToString(); string methodType = context.HttpContext.Request.Method; LimitRequestBannedData data = await limitRequestsService.CheckForBanAndIncreaseRequestsCount(ip, requestsPerTime, time, banTime, controllerName, actionName, methodType, uniqueForEveryActionAndController, useTestMode); if (data.IsBanned) { var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; if (data.ExpiryDate?.CompareTo(TimeSpan.FromSeconds(1)) == -1) { data.ExpiryDate = TimeSpan.FromSeconds(1); } string tryAgainAfter = data.ExpiryDate?.ToString(@"dd\.hh\:mm\:ss"); var contentResult = new ContentResult { Content = JsonSerializer.Serialize( new ApiResponse(400, $"You have made too many requests!Try again after {tryAgainAfter}"), options), ContentType = "application/json", StatusCode = 400 }; context.Result = contentResult; return; } //move to controller await next(); }
public async Task <LimitRequestBannedData> IsBannedAsync(string ip) { if (database.KeyExists(ip + ":banned")) { RedisValueWithExpiry data = await database.StringGetWithExpiryAsync(ip + ":banned"); LimitRequestBannedData returnData = new LimitRequestBannedData() { IsBanned = true, ExpiryDate = data.Expiry }; return(returnData); } return(new LimitRequestBannedData() { IsBanned = false }); //return await database.KeyExistsAsync(ip + ":banned"); }