Knowledge
  • Read Me
  • Programming
    • ASP.NET
      • .NET Libraries
      • ASP.NET Core
        • Helper
          • Encryption
          • CSV Helper
          • String Helper
        • Logging
          • Simple Serilog
        • Middlewares
          • IP Restrictions
          • Request Throttling
          • Request Logging
        • Console
          • Command Line with arguments
        • JSON
      • ASP.NET Framework
      • Testing
        • Resources
        • xUnit.net
      • Naming Conventions
      • REST API Guidelines
    • Database
      • SQL Style Guide
      • MSSQL
        • Installation
          • Install MSSQL on MacOS M1 (ARM64)
        • Looping
        • Table Valued Functions
        • Session State
        • SQL Cheat Sheet
        • Export Pipe Delimited CSV With cmdshell
      • Redis
        • Redis Installation on Mac OS
        • Redis Installation on Docker
    • Java
      • AWS SDK - SSM
      • mTLS HTTP Connection
      • Read Resource Files
    • Javascript
      • Javascript Libraries
    • Python
    • OpenSSL
      • One Way SSL & Two Way SSL
      • Common OpenSSL Commands
      • Create Self-Signed Certificate
    • Misc
      • Git Commands
      • Windows Commands
      • PowerShell Commands
      • Vulnerabilities Dependency Check
      • Replace Filename Command
      • JSON Web Token (JWT)
      • Rabbit MQ Message-Broker
      • Pandoc Convert Document
  • DevOps
    • What is DevOps
    • CI & CD
    • Azure DevOps
  • Tools
    • Development Tools
Powered by GitBook
On this page
  • Attribute code
  • Example usage
  • References

Was this helpful?

  1. Programming
  2. ASP.NET
  3. ASP.NET Core
  4. Middlewares

Request Throttling

PreviousIP RestrictionsNextRequest Logging

Last updated 6 years ago

Was this helpful?

Security in apis are important and we might not want the apis we build to be overly used. This could be to prevent DDoS attacks or to make sure no one tries to brute-force-use your api. To solve this problem we could use a small attribute function that allows for throttling of a specific endpoint.

Attribute code

Example code with logging.

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Caching.Memory;
using Serilog;
using System;
using System.Net;

namespace Sample.Filters
{

    /// <summary>
    /// Request throttling attribute to prevent DDoS attacks 
    /// or to make sure no one tries to brute-force-use your api.
    /// </summary>
    [AttributeUsage(AttributeTargets.Method)]
    public class ThrottleAttribute : ActionFilterAttribute
    {
        /// <summary>
        /// Optional, default gets from ActionExecutingContext ActionDescriptor DisplayName
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Gets and sets the Throttling seconds
        /// </summary>
        public int Seconds { get; set; }

        /// <summary>
        /// Gets and sets the Throttle message. 
        /// Default "You may only perform this action every {n} seconds."
        /// </summary>
        public string Message { get; set; }

        private static MemoryCache Cache { get; } = new MemoryCache(new MemoryCacheOptions());

        public override void OnActionExecuting(ActionExecutingContext c)
        {
            if (string.IsNullOrWhiteSpace(Name))
                Name = c.ActionDescriptor.DisplayName;

            var ipAddress = c.HttpContext.Connection.RemoteIpAddress?.ToString();
            var key = string.Concat(Name, "-", ipAddress);

            if (!Cache.TryGetValue(key, out bool entry))
            {
                var cacheEntryOptions = new MemoryCacheEntryOptions()
                    .SetAbsoluteExpiration(TimeSpan.FromSeconds(Seconds));

                Cache.Set(key, true, cacheEntryOptions);
            }
            else
            {
                if (string.IsNullOrEmpty(Message))
                    Message = "You may only perform this action every {n} seconds.";

                c.Result = new ContentResult { Content = Message.Replace("{n}", Seconds.ToString()) };
                c.HttpContext.Response.StatusCode = (int)HttpStatusCode.Conflict;

                Log.Logger.Information("Throttle filtered from action: {0}, ip: {1}", Name, ipAddress);
            }
        }
    }
}

Example usage

[Route("api/[controller]")]
public class ActionsController : Controller
{
    // GET /api/actions/throttle
    [HttpGet("throttle")]
    // Only allow access every 5 seconds
    [Throttle(Name = "ThrottleTest", Seconds = 5)]
    public IActionResult GetThrottle() => new
    {
        Message = "OK!"
    };

    // GET /api/actions/throttle-2
    [HttpGet("throttle-2")]
    // Only allow access every 5 seconds
    [Throttle(Seconds = 5)]
    public IActionResult GetThrottle2() => new
    {
        Message = "OK!"
    };
}

References

Serilog
Request throttling in .NET Core MVC