{"id":286475,"date":"2021-06-29T14:37:35","date_gmt":"2021-06-29T11:37:35","guid":{"rendered":"https:\/\/en.buradabiliyorum.com\/how-to-rate-limit-requests-in-blazor-asp-net-core-cloudsavvy-it\/"},"modified":"2021-06-29T14:37:35","modified_gmt":"2021-06-29T11:37:35","slug":"how-to-rate-limit-requests-in-blazor-asp-net-core-cloudsavvy-it","status":"publish","type":"post","link":"https:\/\/buradabiliyorum.com\/en\/how-to-rate-limit-requests-in-blazor-asp-net-core-cloudsavvy-it\/","title":{"rendered":"#How To Rate Limit Requests In Blazor\/ASP.NET Core \u2013 CloudSavvy IT"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_84 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6a2950c53f510\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #dd3333;color:#dd3333\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #dd3333;color:#dd3333\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6a2950c53f510\" checked aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-rate-limit-requests-in-blazor-asp-net-core-cloudsavvy-it\/#Why_Rate_Limit_Requests\" >Why Rate Limit Requests?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-rate-limit-requests-in-blazor-asp-net-core-cloudsavvy-it\/#Setting_Up_Rate_Limiting_In_ASPNET_Core\" >Setting Up Rate Limiting In ASP.NET Core<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-rate-limit-requests-in-blazor-asp-net-core-cloudsavvy-it\/#Configuring_Rate_Limiting\" >Configuring Rate Limiting<\/a><\/li><\/ul><\/nav><\/div>\n<p><strong>&#8220;#How To Rate Limit Requests In Blazor\/ASP.NET Core \u2013 CloudSavvy IT&#8221;<\/strong><\/p>\n<div id=\"article-content-area\">\n<img loading=\"lazy\" decoding=\"async\" class=\"type:primaryImage alignnone size-full wp-image-12309\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/06\/74fb9d73.png?width=1198&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"700\" height=\"350\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>If you\u2019re making a public API or website, you\u2019re probably worried about performance. Rate limiting can help prevent abuse from basic DDoS attacks, and it\u2019s pretty easy to set up for Blazor\/ASP.NET Core <a href=\"https:\/\/buradabiliyorum.com\/en\/category\/download-scripts-themes-apps\/\" data-internallinksmanager029f6b8e52c=\"9\" title=\"Download Scripts &amp; Themes &amp; Apps\" target=\"_blank\" rel=\"noopener\">app<\/a>lications.<\/p>\n<h2 role=\"heading\" aria-level=\"2\"><span class=\"ez-toc-section\" id=\"Why_Rate_Limit_Requests\"><\/span>Why Rate Limit Requests?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>There are plenty of reasons to rate limit requests. Most services should probably set some kind of rate limit, because no reasonable human is going to be making 100 requests a second for ten minutes straight. By default, your application is going to respond to every request, so setting a reasonable limit is a good idea.<\/p>\n<p>Of course, your cloud provider may also have DDoS protection. This will usually protect well against Layer 3 and 4 attacks targeting your server. However, you\u2019ll still want make sure your server does everything it can to block attackers from accessing it.<\/p>\n<p>You also have the option of setting the limit much lower to limit requests on public APIs. For example, maybe a certain endpoint takes a lot of processing to respond to the request. You might want to limit this endpoint so that no single IP address can make more than a few requests every couple seconds, limiting stress on your server\/database.<\/p>\n<h2 role=\"heading\" aria-level=\"2\"><span class=\"ez-toc-section\" id=\"Setting_Up_Rate_Limiting_In_ASPNET_Core\"><\/span>Setting Up Rate Limiting In ASP.NET Core<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Blazor as a framework is built on top of ASP.NET Core, which handles all of the under-the-hood stuff for running an HTTP server and responding to requests. So, you\u2019ll need to configure rate limiting for ASP.NET Core. The same steps will apply to anyone not using Blazor.<\/p>\n<p>Rate limiting isn\u2019t a default feature in ASP.NET Core unfortunately. However, there is a very popular NuGet package,\u00a0<code>AspNetCoreRateLimit<\/code>, which does the job quite well. You can install it by right clicking your project in Visual Studio and selecting \u201cManage NuGet Packages\u2026\u201d:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-12307\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/06\/8f69067f.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"670\" height=\"469\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Search for\u00a0<code>AspNetCoreRateLimit<\/code>\u00a0and install it.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-12308\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/06\/9f151c21.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"700\" height=\"229\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>There are a few ways to do rate limiting. If you\u2019re using an API that needs keys, we recommend rate limiting based on API key, which covers all cases. For most people, rate limiting based on IP address is likely fine, and is the default recommended by AspNetCoreRateLimit.<\/p>\n<p>You\u2019ll need to add it as a service to ASP.NET. All services are configured in <code>Startup.cs<\/code>, which adds them with the <code>ConfigureServices(IServiceCollection services)<\/code>\u00a0function.<\/p>\n<p>There\u2019s quite a few services to configure. The first function configures the services to load settings from your configuration file. You\u2019ll also want to add Microsoft\u2019s memory cache if you haven\u2019t already. Then, you\u2019ll need to configure IpRateLimiting from the JSON file, and then add the rate limiter.<\/p>\n<div class=\"wp-geshi-highlight-wrap5\">\n<div class=\"wp-geshi-highlight-wrap4\">\n<div class=\"wp-geshi-highlight-wrap3\">\n<div class=\"wp-geshi-highlight-wrap2\">\n<div class=\"wp-geshi-highlight-wrap\">\n<div class=\"wp-geshi-highlight\">\n<div class=\"csharp\">\n<pre class=\"de1\">            <span class=\"co1\">\/\/ needed to load configuration from appsettings.json <\/span>\n            services<span class=\"sy0\">.<\/span><span class=\"me1\">AddOptions<\/span><span class=\"br0\">(<\/span><span class=\"br0\">)<\/span><span class=\"sy0\">;<\/span>\n\u00a0\n            <span class=\"co1\">\/\/ needed to store rate limit counters and ip rules<\/span>\n            services<span class=\"sy0\">.<\/span><span class=\"me1\">AddMemoryCache<\/span><span class=\"br0\">(<\/span><span class=\"br0\">)<\/span><span class=\"sy0\">;<\/span>\n\u00a0\n            <span class=\"co1\">\/\/load <a href=\"https:\/\/buradabiliyorum.com\/en\/category\/general\/\" data-internallinksmanager029f6b8e52c=\"3\" title=\"General\" target=\"_blank\" rel=\"noopener\">general<\/a> configuration from appsettings.json<\/span>\n            services<span class=\"sy0\">.<\/span><span class=\"me1\">Configure<\/span><span class=\"br0\">(<\/span>Configuration<span class=\"sy0\">.<\/span><span class=\"me1\">GetSection<\/span><span class=\"br0\">(<\/span><span class=\"st0\">\"IpRateLimiting\"<\/span><span class=\"br0\">)<\/span><span class=\"br0\">)<\/span><span class=\"sy0\">;<\/span>\n\u00a0\n            <span class=\"co1\">\/\/ inject counter and rules stores<\/span>\n            services<span class=\"sy0\">.<\/span><span class=\"me1\">AddInMemoryRateLimiting<\/span><span class=\"br0\">(<\/span><span class=\"br0\">)<\/span><span class=\"sy0\">;<\/span>\n\u00a0\n            <span class=\"co1\">\/\/ configuration (resolvers, counter key builders)<\/span>\n            services<span class=\"sy0\">.<\/span><span class=\"me1\">AddSingleton<\/span><span class=\"sy0\">&lt;<\/span>IRateLimitConfiguration, RateLimitConfiguration<span class=\"sy0\">&gt;<\/span><span class=\"br0\">(<\/span><span class=\"br0\">)<\/span><span class=\"sy0\">;<\/span><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Also in <code>Startup.cs<\/code>, you\u2019ll need to configure the application builder to use IP rate limiting.<\/p>\n<pre>app.UseIpRateLimiting();<\/pre>\n<p>Keep in mind that this uses in-memory rate limiting, which is per-instance. If you\u2019re load balancing your application, you\u2019ll need to use a distributed memory store like Redis, which this package <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/github.com\/stefanprodan\/AspNetCoreRateLimit\/wiki\/IpRateLimitMiddleware#setup\">also has support for.<\/a><\/p>\n<h2 role=\"heading\" aria-level=\"2\"><span class=\"ez-toc-section\" id=\"Configuring_Rate_Limiting\"><\/span>Configuring Rate Limiting<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Once it\u2019s added to ASP.NET, you\u2019ll need to head over to your <code>appsettings.json<\/code>\u00a0configuration file to set it up. The configuration looks something like the following:<\/p>\n<pre>\"IpRateLimiting\": {&#13;\n    \"EnableEndpointRateLimiting\": false,&#13;\n    \"StackBlockedRequests\": true,&#13;\n    \"RealIpHeader\": \"X-Real-IP\",&#13;\n    \"ClientIdHeader\": \"X-ClientId\",&#13;\n    \"HttpStatusCode\": 429,&#13;\n    \"IpWhitelist\": [ \"127.0.0.1\", \"::1\/10\", \"192.168.0.0\/24\" ],&#13;\n    \"EndpointWhitelist\": [ \"get:\/api\/license\", \"*:\/api\/status\" ],&#13;\n    \"ClientWhitelist\": [ \"dev-id-1\", \"dev-id-2\" ],&#13;\n    \"GeneralRules\": [&#13;\n      {&#13;\n        \"Endpoint\": \"*\",&#13;\n        \"Period\": \"1s\",&#13;\n        \"Limit\": 2&#13;\n      },&#13;\n      {&#13;\n        \"Endpoint\": \"*\",&#13;\n        \"Period\": \"15m\",&#13;\n        \"Limit\": 100&#13;\n      },&#13;\n      {&#13;\n        \"Endpoint\": \"*\",&#13;\n        \"Period\": \"12h\",&#13;\n        \"Limit\": 1000&#13;\n      },&#13;\n      {&#13;\n        \"Endpoint\": \"*\",&#13;\n        \"Period\": \"7d\",&#13;\n        \"Limit\": 10000&#13;\n      }&#13;\n    ]&#13;\n  }<\/pre>\n<p>First off, if you plan to rate limit certain endpoints differently, you\u2019ll want to turn on\u00a0EnableEndpointRateLimiting, which is false by default.<\/p>\n<p>StackBlockedRequests will make any blocked requests count towards the counter. Basically, with this off, anyone making requests over and over will be served X responses per period. With it on, they\u2019ll work up the max responses very quickly, and then won\u2019t be responded too again.<\/p>\n<p>RealIpHeader and ClientIdHeader used when your server is behind a reverse proxy, which is a common set up. Since the requests will always come from the proxy server, the proxy sets a header with the user\u2019s actual info. You\u2019ll need to check your proxy and ensure that this header is set correctly, or else the rate limiter will treat everyone as the same IP.<\/p>\n<p>Then, there are three whitelists, one for IPs, client IDs, and endpoints. You can remove these if you don\u2019t need them.<\/p>\n<p>Then, you\u2019ll need to configure each endpoint, as well as a period and limit. A wildcard will cover everything and is the only thing that works with EnableEndpointRateLimiting set to false. If it\u2019s not, you can define endpoints using <code>{HTTP_VERB}{PATH}<\/code>, including wildcards, so\u00a0\u00a0<code>*:\/api\/values<\/code>\u00a0will match all GET and POST requests to <code>\/api\/values<\/code>.<\/p>\n<p>You\u2019ll want to make sure that your endpoint matches a file, and not a directory. In my case, <code>*:\/download\/*\/*<\/code> was a valid endpoint, but <code>*:\/download\/*\/*\/<\/code>\u00a0was not, because of the trailing slash.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-12316\" src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/06\/2f948508.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"400\" height=\"124\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>This default config includes an IP whitelist for localhost, which you\u2019ll need to comment out if you\u2019re doing testing. But, you should be able to test your configuration by setting the limit very low, like 5 per minute, and making a bunch of requests. You should get this error, \u201cAPI calls quota exceeded,\u201d which means it\u2019s working properly.<\/p>\n<p>There\u2019s a lot more that this package can do, so if you have more specific needs than this, we recommend <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/github.com\/stefanprodan\/AspNetCoreRateLimit\/wiki\/IpRateLimitMiddleware\">checking out their documentation<\/a> and seeing what\u2019s possible.\n<\/div>\n<blockquote><p><strong><span style=\"color: #ff6600;\">If you liked the article, do not forget to share it with your friends. Follow us on\u00a0<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/news.google.com\/publications\/CAAqBwgKMLG0nwswvr63Aw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Google News<\/a><\/span>\u00a0too, click on the star and choose us from your favorites.<\/span><\/strong><\/p><\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\">For forums sites go to <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/forum.buradabiliyorum.com\/\" target=\"_blank\" rel=\"noopener\">Forum.BuradaBiliyorum.Com<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\"><strong>If you want to read more like this article, you can visit our <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/en.buradabiliyorum.com\/technology\/\" target=\"_blank\" rel=\"noopener\">Technology category.<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<p><span style=\"color: black;\"><a style=\"color: #ff9900;\" href=\"https:\/\/www.cloudsavvyit.com\/12306\/how-to-rate-limit-requests-in-blazor-asp-net-core\/\" target=\"_blank\" rel=\"noopener\">Source<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;#How To Rate Limit Requests In Blazor\/ASP.NET Core \u2013 CloudSavvy IT&#8221; If you\u2019re making a public API or website, you\u2019re probably worried about performance. Rate limiting can help prevent abuse from basic DDoS attacks, and it\u2019s pretty easy to set up for Blazor\/ASP.NET Core applications. Why Rate Limit Requests? There are plenty of reasons to&#8230;<\/p>\n","protected":false},"author":1,"featured_media":286476,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/06\/74fb9d73.png","fifu_image_alt":"","footnotes":""},"categories":[18],"tags":[],"class_list":["post-286475","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology"],"_links":{"self":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/286475","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/comments?post=286475"}],"version-history":[{"count":0,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/286475\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media\/286476"}],"wp:attachment":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media?parent=286475"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/categories?post=286475"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/tags?post=286475"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}