diff --git a/.gitignore b/.gitignore index 980792e..38fb279 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,11 @@ pom.xml.next release.properties dependency-reduced-pom.xml +##################### +target/ +temp-repo/ +.m2/ + ############################################ # Logs ############################################ diff --git a/pom.xml b/pom.xml index 368e4be..086208a 100644 --- a/pom.xml +++ b/pom.xml @@ -87,22 +87,25 @@ org.flywaydb flyway-core + org.flywaydb flyway-database-postgresql + com.bucket4j bucket4j-core - 8.6.0 + 8.9.0 com.bucket4j bucket4j-redis - 8.6.0 + 8.9.0 + org.springframework.boot spring-boot-starter-data-redis diff --git a/src/main/java/com/vimaltech/contactapi/security/RedisRateLimitFilter.java b/src/main/java/com/vimaltech/contactapi/security/IpRateLimitFilter.java similarity index 60% rename from src/main/java/com/vimaltech/contactapi/security/RedisRateLimitFilter.java rename to src/main/java/com/vimaltech/contactapi/security/IpRateLimitFilter.java index 3d15d9e..b334d1b 100644 --- a/src/main/java/com/vimaltech/contactapi/security/RedisRateLimitFilter.java +++ b/src/main/java/com/vimaltech/contactapi/security/IpRateLimitFilter.java @@ -2,51 +2,30 @@ import io.github.bucket4j.Bandwidth; import io.github.bucket4j.Bucket; -import io.github.bucket4j.BucketConfiguration; -import io.github.bucket4j.distributed.proxy.ProxyManager; -import io.github.bucket4j.redis.lettuce.cas.LettuceBasedProxyManager; - -import io.lettuce.core.RedisClient; -import io.lettuce.core.RedisURI; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; import java.time.Duration; +import java.util.Map; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; @Component @Profile("prod") -public class RedisRateLimitFilter extends OncePerRequestFilter { - - private final ProxyManager proxyManager; - - public RedisRateLimitFilter( - @Value("${spring.data.redis.host}") String host, - @Value("${spring.data.redis.port}") int port - ) { - - RedisURI redisURI = RedisURI.Builder.redis(host) - .withPort(port) - .build(); - - RedisClient redisClient = RedisClient.create(redisURI); +public class IpRateLimitFilter extends OncePerRequestFilter { - this.proxyManager = LettuceBasedProxyManager - .builderFor(redisClient) - .build(); - } + private final Map buckets = new ConcurrentHashMap<>(); - private BucketConfiguration configuration() { - return BucketConfiguration.builder() + private Bucket createBucket() { + return Bucket.builder() .addLimit(Bandwidth.simple(10, Duration.ofMinutes(1))) .build(); } @@ -66,8 +45,7 @@ protected void doFilterInternal(HttpServletRequest request, .map(s -> s.split(",")[0].trim()) .orElse(request.getRemoteAddr()); - Bucket bucket = proxyManager.builder() - .build(("ip:" + ip).getBytes(), this::configuration); + Bucket bucket = buckets.computeIfAbsent(ip, k -> createBucket()); if (bucket.tryConsume(1)) { filterChain.doFilter(request, response);