Example #1
0
        private static string BuildRequestKey(
            ThrottlingProperties propertiesSet,
            ThrottlingPeriod period,
            NancyContext context,
            params string[] requestKeys)
        {
            using (var ms = new MemoryStream())
                using (var sw = new StreamWriter(ms, Encoding.UTF8))
                {
                    if (propertiesSet.HasFlag(ThrottlingProperties.RemoteIp))
                    {
                        sw.Write(context.GetClientHost());
                    }

                    if (propertiesSet.HasFlag(ThrottlingProperties.Method))
                    {
                        sw.Write(context.Request.Method);
                    }

                    if (propertiesSet.HasFlag(ThrottlingProperties.Path))
                    {
                        sw.Write(context.Request.Path);
                    }

                    sw.Write(period);

                    if (requestKeys != null)
                    {
                        foreach (var key in requestKeys)
                        {
                            sw.Write(key);
                        }
                    }

                    sw.Flush();
                    ms.Position = 0;
                    using (var algorithm = new SHA1Managed())
                    {
                        var hash = algorithm.ComputeHash(ms);
                        return(Convert.ToBase64String(hash));
                    }
                }
        }
        private static async Task LogRequest(
            NancyContext ctx,
            ILifetimeScope requestContainer,
            HttpStatusCode?statusCode = null)
        {
            var repository = requestContainer.Resolve <IAccessLogRepository>();
            var logger     = requestContainer.Resolve <ILogger>();

            try
            {
                var processingTime = CalculateProcessingTime(ctx);

                var sensitiveInfoInPathRegex = ctx.GetRegexForSensitiveInfoInPath();
                var actionStr = sensitiveInfoInPathRegex != null
                    ? sensitiveInfoInPathRegex.Replace(ctx.Request.Path, SensitiveInfoReplacement)
                    : ctx.Request.Path;

                var logEntry = new AccessLogEntry
                {
                    Action         = Truncate(actionStr, 255),
                    Method         = Truncate(ctx.Request.Method, 15),
                    ClientIp       = Truncate(ctx.GetClientHost(), 255),
                    StatusCode     = (int?)(statusCode ?? ctx.Response?.StatusCode),
                    ProcessedAt    = DateTime.UtcNow,
                    UserAgent      = Truncate(string.Join(", ", ctx.Request.Headers["User-Agent"]), 255),
                    UserId         = Truncate(ctx.CurrentUser?.Identity?.Name, 128),
                    ProcessingTime = processingTime,
                    Referer        = Truncate(ctx.Request.Headers.Referrer, 255),
                    AcceptLanguage = ctx.Request.Headers["Accept-Language"].Any()
                        ? Truncate(string.Join("|", ctx.Request.Headers["Accept-Language"]), 255)
                        : null,
                };

                await repository.Insert(logEntry);
            }
            catch (Exception ex)
            {
                logger.Error(ex, "LogRequest error");
            }
        }
Example #3
0
        private Response CheckThrottlingLimitHook(
            NancyContext context,
            ThrottlingProperties propertiesSet,
            ThrottlingPeriod period,
            int requestCountLimit,
            Func <NancyContext, bool> checkIf = null,
            Func <NancyContext, bool> skipIf  = null,
            params string[] requestKeys)
        {
            if (checkIf != null && !checkIf(context))
            {
                return(null);
            }

            if (skipIf != null && skipIf(context))
            {
                return(null);
            }

            var key            = BuildRequestKey(propertiesSet, period, context, requestKeys);
            var expirationTime = CalculateExpirationTime(period);

            var counterValue = IncrementCounter(key, expirationTime);

            if (IsLimitExceeded(requestCountLimit, counterValue))
            {
                if (IsNeedToLog(requestCountLimit, counterValue))
                {
                    logger.Error($"Flood detected ({counterValue} in {period.ToString()} allowed {requestCountLimit})" +
                                 $" on path: {context?.Request?.Path}" +
                                 $" ip: {context?.GetClientHost()}");
                }
                return(new Response
                {
                    StatusCode = HttpStatusCode.TooManyRequests
                });
            }

            return(null);
        }