Closed Thwaitesy closed 7 years ago
Here is my startup.cs code
/* This will be processed first in the pipeline - it is much faster
*
* + 50 requests per second, per endpoint, per IP address
*
*/
config.MessageHandlers.Add(new ThrottlingHandler()
{
Policy = new ThrottlePolicy(perSecond: 50)
{
IpThrottling = true,
IpWhitelist = new List<string> { "127.0.0.1", "192.168.0.0/24" }, //Local host & Local network
EndpointThrottling = true,
},
Logger = new ThrottleLogger(),
Repository = new CacheRepository(),
});
/* This is handled second - It is turned on by [EnableThrottling] attributes
*
* + No IP address throttling
* + No endpoint throttling
*
*/
config.Filters.Add(new ThrottlingFilter()
{
Policy = new ThrottlePolicy
{
IpWhitelist = new List<string> { "127.0.0.1", "192.168.0.0/24" }, //Local host & Local network
},
Logger = new ThrottleLogger(),
Repository = new CacheRepository(),
});
Here is the controller code:
[HttpPost]
[Route("")]
[AllowAnonymous]
[EnableThrottling(PerHour = 150)]
public HttpResponseMessage CreateUser(CreateUser.Request request)
Hi @Thwaitesy, you don't need the handler, the filter should apply on all actions. Removed the handler and your setup is good.
Or you could use only the ThrottlingHandler
to block the requests before the http controller dispatcher, it's faster.
You should configure it like this:
config.MessageHandlers.Add(new ThrottlingHandler()
{
Policy = new ThrottlePolicy(perSecond: 50)
{
IpThrottling = true,
IpWhitelist = new List<string> { "127.0.0.1", "192.168.0.0/24" }, //Local host & Local network
EndpointThrottling = true,
EndpointRules = new Dictionary<string, RateLimits>
{
{ "users/CreateUser", new RateLimits { PerHour = 150} }
}
},
Logger = new ThrottleLogger(),
Repository = new CacheRepository(),
});
Replace the "users/CreateUser"
with your controller/action name.
Ok cool.
Can you add wildcard to the EndpointRules?
E.g. "api/users/{userid}/reports" or "api/users/*/reports"
Wildcards are not supported, the matching is done using contains
.
var rules = Policy.EndpointRules.Where(x => identity.Endpoint.Contains(x.Key.ToLowerInvariant())).ToList();
using x.Key.ToLowerInvariant()
instead of a case-insensitive equality comparison is a performance anti-pattern.
It would be much better to construct the dictionary with a different comparitor
@IDisposable you are right, thanks for pointing this to me.
I've changed it to:
var rules = Policy.EndpointRules.Where(x => identity.Endpoint.IndexOf(x.Key, 0, StringComparison.InvariantCultureIgnoreCase) != -1).ToList();
Hi - Awesome Library!
We have had someone abusing our API, mainly creating tonnes of user accounts (13 thousand over a period of 3 hours or so).
Here is what I am trying to achieve:
Basically - this means that while we are sleeping (say 10 hours) the attacker could only create a maximum of 1500 accounts. It also means that their could only be 150 "Real" user accounts per hour... We can manage that number over time but for now thats more than required.
At this stage this is what I have:
My question: Will the ThrottlingHandler & ThrottlingFilter work independent of each other? Or do they inherit each other's policies? And - does the above look ok?
Cheers, Sam