Home > Mobile >  How to let Spring Cloud Gateway to forward the real client address to services
How to let Spring Cloud Gateway to forward the real client address to services

Time:07-30

I'm trying to build my own Spring Cloud app for the first time.
My Spring Cloud Gateway(SCG from now on) sits right behind the nginx.
The SCG relays requests from nginx to my Eureka server.
And my Eureka clients eventually receive these requests.

The problem is, when one of the Eureka client services attempts to extract
the original client's IP address like below, the retrieved address is of the host that running
nginx, instead of client's one.

@ResponseBody
public ResponseEntity<?> controllerMethod (
        @RequestBody MyDto myDto
        , HttpServletRequest request
) throws Exception {
   String clientAddress = null;
   if (Strings.isBlank(request.getHeader("X-Forwarded-For")) == true) {
       clientAddress = request.getHeader("X-FORWARDED-FOR");

       if (Strings.isBlank(clientAddress) == true) {
          clientAddress = request.getRemoteAddr();
       }
   }
   // ...
}

So I tried the workaround described as another thread mentioned below,
but it seems not working to me.

https://stackoverflow.com/a/67018627/2318920

And I tried to apply the guide from Spring's official reference document,
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#modifying-the-way-remote-addresses-are-resolved I can't picture how the entire GatewayConfig.java file in the example would look like.

Therefore, I wrote my GatewayConfig.java like below.

package root.project.path.config;

import java.net.InetSocketAddress;

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.support.ipresolver.XForwardedRemoteAddressResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.ServerWebExchange;

import reactor.core.publisher.Mono;


@Configuration
public class GatewayConfig implements KeyResolver {

    @Bean
    @Override
    public Mono<String> resolve(ServerWebExchange exchange) {
        XForwardedRemoteAddressResolver resolver = XForwardedRemoteAddressResolver.maxTrustedIndex(1);
        InetSocketAddress inetSocketAddress = resolver.resolve(exchange);
        return Mono.just(inetSocketAddress.getAddress().getHostAddress());
    }
    
}   // END: public class GatewayConfig

Then I start my SCG service, it prints the error message like following and stops.

Jul 27 20:21:33 account gateway[2219027]: ***************************
Jul 27 20:21:33 account gateway[2219027]: APPLICATION FAILED TO START
Jul 27 20:21:33 account gateway[2219027]: ***************************
Jul 27 20:21:33 account gateway[2219027]: Description:
Jul 27 20:21:33 account gateway[2219027]: Parameter 0 of method resolve in root.project.path.config.GatewayConfig required a bean of type 'org.springframework.web.server.ServerWebExchange' that could not be found.
Jul 27 20:21:33 account gateway[2219027]: Action:
Jul 27 20:21:33 account gateway[2219027]: Consider defining a bean of type 'org.springframework.web.server.ServerWebExchange' in your configuration.

I think I miscomprehend something. But I'm not able to find what it is now.
Please help me.

CodePudding user response:

I found the reason. Actually this issue was not occurred by the SCG.

Under the identical settings with my question, the server.forward-headers-strategy property item at application.properties (or application.yml in my source tree) in Eureka client services were set as framework. After replacing it with native, request.getHeader("X-Forwarded-For") part in the controller's method starts to return the end client's IP address.

Although it's not the problem with SCG (at least to me), but I hope this article helps someone who may be struggling with the same symptom like this

  • Related