Restrict access to public service many times
Asked Answered
A

2

4

I have such situation. Imagine there is a public REST service. What we don't want, is for someone, to be able to access this service many times in short period of time, because they will be able to block our database (essentially a DDOS attack, I presume?).

Is there a way to effectively protect against this type of attack? Technology we use is Spring/Spring Security.

Arnoldoarnon answered 22/9, 2016 at 9:11 Comment(1)
You are looking for request throttling. This is best done either at the Intrusion Detection System (which should detect DDoS attacks) or Internet Gateway (if you do not have an IDS). Failing that, the best place to implement throttling would be at the web server. Apache, IIS and Nginx all support throttling.Amary
E
3

If you are using Spring Boot There is a fairly new opensource project which handles this:

https://github.com/weddini/spring-boot-throttling

Declarative approach of throttling control over the Spring services. @Throttling annotation helps you to limit the number of service method calls per java.util.concurrent.TimeUnit for a particular user, IP address, HTTP header/cookie value, or using Spring Expression Language (SpEL).

Obviously this wouldn't prevent DDOS attacks at the web server level, but it would help limit access to long running queries or implement a fair usage policy.

Elijah answered 16/5, 2018 at 15:32 Comment(1)
this solution requires java 8+Interbreed
R
1

For those interested in the subject, spring-boot-throttling seems no longer maintained.

So, I take a look on bucket4j

The use is quite simple: There are 3 main objects:

  • Bucket : Interface allowing to define the total capacity of available tokens. It also provides the methods to consume the tokens.
  • Bandwidth : Class allowing to define the limits of the bucket.
  • Refill : Class allowing to define the way the bucket will be fed, with new tokens.

Example with simple Spring Boot controller:

@RestController
public class TestLimit {
    
    private Bucket bucket = null;
    
    public MsGeneratorController() {
        Bandwidth limit = Bandwidth.classic(120, Refill.greedy(120, Duration.ofMinutes(1)));
        this.bucket = Bucket4j.builder().addLimit(limit).build();
    }

    @RequestMapping(path = "/test-limit/", method = RequestMethod.GET)
    public ResponseEntity<String> download() throws IOException {

        if (this.bucket.tryConsume(1)) {
            return ResponseEntity.status(HttpStatus.OK).build();
        }else {
            return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS).build();
        }
    }
}

In this case, we have a limit of 120 requests per minute, with bucket capacity 120 and a refill rate of 120 tokens per minute.

If we exceed this limit, we will receive an HTTP 429 code (TOO_MANY_REQUESTS).

Reveille answered 2/1, 2022 at 22:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.