public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { var cacheProvider = context.HttpContext.RequestServices.GetService <IDistributedCache>(); var captchaOptions = context.HttpContext.RequestServices.GetService <IOptions <CaptchaOptions> >()?.Value ?? new CaptchaOptions(); var descriptor = context?.ActionDescriptor as ControllerActionDescriptor; if (!captchaOptions.IsCaptchaEnabled) { return; } string actionName = descriptor.ActionName; string controllerName = descriptor.ControllerName; if (captchaOptions.IsEnabledThreshold) { string thresholdKeyName = $"{controllerName}_{actionName}_{CaptchaType.ToString()}_Threshold"; if (Threshold == -1) { Threshold = captchaOptions.Threshold; } } if (captchaOptions.IsEnabledDuration) { string durationKeyName = $"{controllerName}_{actionName}_{CaptchaType.ToString()}_Duration"; if (Duration == -1) { Duration = captchaOptions.Duration; } } string cacheKeyPattern = context.GetCacheKey(captchaOptions.DomainName, CaptchaType, FieldName, GlobalCacheName); int cacheVisitedCount = cacheProvider.Get <int>(cacheKeyPattern); if (cacheVisitedCount >= Threshold) { var tokenHeader = context.HttpContext?.Request?.Headers?.TryGetValue( captchaOptions.CaptchaTokenHeaderName, out StringValues token); if (tokenHeader.HasValue && !string.IsNullOrEmpty(token)) { await CheckCaptchaTokenAsync(context, cacheProvider, cacheKeyPattern, cacheVisitedCount, captchaOptions, token.ToString()); } else { AddToCache(cacheProvider, cacheKeyPattern, cacheVisitedCount); context.Result = new ContentResult() { Content = "Too Many Requests", StatusCode = (int)HttpStatusCode.TooManyRequests }; } } else { AddToCache(cacheProvider, cacheKeyPattern, cacheVisitedCount); } await base.OnActionExecutionAsync(context, next); }