You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I took my rate limiter out of my Spring BFF, and put it into my Spring Rest-API as I wanted it to be user specific (and apply different rate limits, depending on the class of user)
So I created my rate limiter.
Rate Limiter
@Component
internal class RequestRateLimiterConfig(
private val redisRateLimiter: RedisRateLimiter,
private val defaultKeyResolver: KeyResolver
) : AbstractGatewayFilterFactory<RequestRateLimiterConfig.Config>(Config::class.java) {
companion object {
const val RATE_LIMITER_ID = "redis-rate-limiter"
}
private val logger = LoggerFactory.getLogger(RequestRateLimiterConfig::class.java)
override fun apply(config: Config): GatewayFilter {
return GatewayFilter { exchange: ServerWebExchange, chain ->
logger.info("Entering rate limiter filter...")
val keyMono = defaultKeyResolver.resolve(exchange)
keyMono
.flatMap { key ->
if (key.isNullOrEmpty()) {
logger.warn("No key resolved. Blocking request.")
LocalExceptionHandlers.missingKey(exchange)
} else {
logger.info("Resolved key: $key")
redisRateLimiter.isAllowed(RATE_LIMITER_ID, key)
.flatMap { response ->
if (!response.isAllowed) {
logger.warn("Rate limit exceeded for key: $key")
LocalExceptionHandlers.rateLimitExceeded(exchange)
} else {
logger.info("Rate limit allowed for key: $key")
chain.filter(exchange)
}
}
}
}.then()
}
}
override fun newConfig(): Config {
return Config()
}
class Config
}
/**
* More Rate Limiter configuration
*/
@Configuration
internal class RedisRateLimiterConfig(
private val authorizationProperties: AuthorizationProperties,
) {
private val logger = LoggerFactory.getLogger(RedisRateLimiterConfig::class.java)
/**
* Redis Rate Limited
*/
@Bean
fun redisRateLimiter(): RedisRateLimiter {
return RedisRateLimiter(1, 1, 1)
}
/**
* Default Key Resolver
*/
@Bean
fun defaultKeyResolver(): KeyResolver {
return KeyResolver { exchange: ServerWebExchange ->
// fetch authentication context and resolve provider ID if available
ReactiveSecurityContextHolder.getContext()
.doOnNext { context -> logger.info("Security context found: ${context.authentication}") }
.mapNotNull { it.authentication as? JwtAuthenticationToken }
.flatMap { authentication ->
val providerId = authentication?.token?.getClaimAsString(authorizationProperties.authProviderSubjectClaim)
if (providerId.isNullOrBlank()) {
logger.warn("No provider ID found in token claims.")
Mono.just("")
} else {
logger.info("Resolved provider ID for Rate Limiting: $providerId")
Mono.just(providerId)
}
}
.switchIfEmpty(
Mono.defer {
logger.warn("No authentication found in security context.")
Mono.just("")
}
)
}
}
}
But nothing was triggering, I could not see any logs.
So I added this (so all routes are routed to this same server).
Note, I do not think this is ideal in a load balancer environment, as the request has already reached the resource server, and this is effectively forwarding it back out to itself.
But even with this, I get no logged information. I send a request to a hello world endpoint, and I get all 25 back very quickly in < 1 second (when the rate limiter should really kick in after 1 request)
Route Builder
@Configuration
internal class RoutingConfig(
private val serverProperties: ServerProperties,
private val rateLimitingFilter: RequestRateLimiterConfig
) {
private val logger = LoggerFactory.getLogger(RoutingConfig::class.java)
@Bean
fun routeLocator(builder: RouteLocatorBuilder): RouteLocator {
return builder.routes()
.route("resource-server") { r ->
r.path("/**") // Match all paths
.filters { f ->
logger.info("Entering resource-server route")
f.filter(rateLimitingFilter.apply(rateLimitingFilter.newConfig()))
}
.uri(serverProperties.resourceServerUri)
}
.build()
}
}
Yaml
Here is my yaml config
# default spring settings
spring:
# spring cloud settings
cloud:
# spring gateway settings
gateway:
metrics:
enabled: true
tags:
path:
enabled: true
OAuth Resource Server
And my resource server security chain is quite standard:
I took my rate limiter out of my Spring BFF, and put it into my Spring Rest-API as I wanted it to be user specific (and apply different rate limits, depending on the class of user)
So I created my rate limiter.
Rate Limiter
But nothing was triggering, I could not see any logs.
So I added this (so all routes are routed to this same server).
Note, I do not think this is ideal in a load balancer environment, as the request has already reached the resource server, and this is effectively forwarding it back out to itself.
But even with this, I get no logged information. I send a request to a hello world endpoint, and I get all 25 back very quickly in < 1 second (when the rate limiter should really kick in after 1 request)
Route Builder
Yaml
Here is my yaml config
OAuth Resource Server
And my resource server security chain is quite standard:
I'm not sure where I've gone wrong? Maybe its the yaml?
Would appreciate any help
The text was updated successfully, but these errors were encountered: