From 3b31ba4f998071c01c6560d04321edff2f9f6bd6 Mon Sep 17 00:00:00 2001 From: Harry9656 Date: Thu, 8 Dec 2022 09:09:03 +0100 Subject: [PATCH] JAVA-5958: Ratelimit with client ip address (#13067) * JAVA-5958: Ratelimit with client ip address Co-authored-by: Harpal Singh --- .../ipaddress/IpAddressApplication.java | 38 +++++++++++++++++++ .../ProxiedClientAddressResolver.java | 21 ++++++++++ .../SimpleClientAddressResolver.java | 23 +++++++++++ .../ipaddress-application.properties | 6 +++ 4 files changed, 88 insertions(+) create mode 100644 spring-cloud-modules/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/ipaddress/IpAddressApplication.java create mode 100644 spring-cloud-modules/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/ipaddress/ProxiedClientAddressResolver.java create mode 100644 spring-cloud-modules/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/ipaddress/SimpleClientAddressResolver.java create mode 100644 spring-cloud-modules/spring-cloud-gateway/src/main/resources/ipaddress-application.properties diff --git a/spring-cloud-modules/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/ipaddress/IpAddressApplication.java b/spring-cloud-modules/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/ipaddress/IpAddressApplication.java new file mode 100644 index 0000000000..472c331404 --- /dev/null +++ b/spring-cloud-modules/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/ipaddress/IpAddressApplication.java @@ -0,0 +1,38 @@ +package com.baeldung.springcloudgateway.ipaddress; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter; +import org.springframework.cloud.gateway.route.RouteLocator; +import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.PropertySource; + +@SpringBootApplication() +@PropertySource("classpath:ipaddress-application.properties") +public class IpAddressApplication { + public static void main(String[] args) { + SpringApplication.run(IpAddressApplication.class, args); + } + + @Bean + public RouteLocator myRoutes(RouteLocatorBuilder builder) { + return builder.routes() + .route("requestratelimiter_route", p -> p + .path("/example") + .filters(f -> f.requestRateLimiter(r -> r.setRateLimiter(redisRateLimiter()))) + .uri("http://example.org")) + .route("ipaddress_route", p -> p + .path("/example2") + .filters(f -> f.requestRateLimiter(r -> r.setRateLimiter(redisRateLimiter()) + .setDenyEmptyKey(false) + .setKeyResolver(new SimpleClientAddressResolver()))) + .uri("http://example.org")) + .build(); + } + + @Bean + public RedisRateLimiter redisRateLimiter() { + return new RedisRateLimiter(1, 1, 1); + } +} diff --git a/spring-cloud-modules/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/ipaddress/ProxiedClientAddressResolver.java b/spring-cloud-modules/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/ipaddress/ProxiedClientAddressResolver.java new file mode 100644 index 0000000000..25b1fbcf1f --- /dev/null +++ b/spring-cloud-modules/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/ipaddress/ProxiedClientAddressResolver.java @@ -0,0 +1,21 @@ +package com.baeldung.springcloudgateway.ipaddress; + +import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver; +import org.springframework.cloud.gateway.support.ipresolver.XForwardedRemoteAddressResolver; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import java.net.InetSocketAddress; + +@Primary +@Component +public class ProxiedClientAddressResolver implements KeyResolver { + @Override + public Mono resolve(ServerWebExchange exchange) { + XForwardedRemoteAddressResolver resolver = XForwardedRemoteAddressResolver.maxTrustedIndex(1); + InetSocketAddress inetSocketAddress = resolver.resolve(exchange); + return Mono.just(inetSocketAddress.getAddress().getHostAddress()); + } +} diff --git a/spring-cloud-modules/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/ipaddress/SimpleClientAddressResolver.java b/spring-cloud-modules/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/ipaddress/SimpleClientAddressResolver.java new file mode 100644 index 0000000000..904fd4c193 --- /dev/null +++ b/spring-cloud-modules/spring-cloud-gateway/src/main/java/com/baeldung/springcloudgateway/ipaddress/SimpleClientAddressResolver.java @@ -0,0 +1,23 @@ +package com.baeldung.springcloudgateway.ipaddress; + +import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.util.Optional; + +@Component +public class SimpleClientAddressResolver implements KeyResolver { + @Override + public Mono resolve(ServerWebExchange exchange) { + return Optional.ofNullable(exchange.getRequest().getRemoteAddress()) + .map(InetSocketAddress::getAddress) + .map(InetAddress::getHostAddress) + .map(Mono::just) + .orElse(Mono.empty()); + } +} + diff --git a/spring-cloud-modules/spring-cloud-gateway/src/main/resources/ipaddress-application.properties b/spring-cloud-modules/spring-cloud-gateway/src/main/resources/ipaddress-application.properties new file mode 100644 index 0000000000..ebec52403a --- /dev/null +++ b/spring-cloud-modules/spring-cloud-gateway/src/main/resources/ipaddress-application.properties @@ -0,0 +1,6 @@ +server.port=8081 +spring.redis.database=0 +spring.redis.host=localhost +spring.redis.port=16379 +spring.redis.password=mypass +spring.redis.timeout=60000