在 Spring 云网关中获取真实客户端 IP 地址

Get real client IP address in Spring Cloud Gateway

我在 Spring 云网关 (SCG) 中实施速率限制。我使用以下代码获得客户端 IP 地址

@Component
public class RemoteAddressKeyResolver implements KeyResolver {
    @Override
    public Mono<String> resolve(ServerWebExchange exchange) {
        return Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
    }
}

我的 SCG 在代理后面,因此它获取的是代理地址,而不是真实的客户端地址。如何获取真实客户地址?

您可以检查您的请求 headers 密钥,例如 X-Forwarded-For(取决于您的代理设置)

The X-Forwarded-For (XFF) header is a de-facto standard header for identifying the originating IP address of a client connecting to a web server through an HTTP proxy or a load balancer.

getFirst 将return 原始ip

exchange.getRequest().getHeaders().getFirst("X-Forwarded-For")

我找到了解决办法!有一个RemoteAddressResolver的实现是XForwardedRemoteAddressResolver。直接用就好了,不用再去实现逻辑了。

@Component
public class RemoteAddressKeyResolver implements KeyResolver {
    @Override
    public Mono<String> resolve(ServerWebExchange exchange) {
        XForwardedRemoteAddressResolver resolver = XForwardedRemoteAddressResolver.maxTrustedIndex(1);
        InetSocketAddress inetSocketAddress = resolver.resolve(exchange);
        return Mono.just(inetSocketAddress.getAddress().getHostAddress());
    }
}

就这么简单!

    return exchange -> {
        // String origin = exchange.getRequest().getHeaders().getFirst("X-Forwarded-For");
        // if (origin == null) 
        // origin = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
        // return Mono.just(origin);
        XForwardedRemoteAddressResolver resolver = XForwardedRemoteAddressResolver.maxTrustedIndex(1);
        InetSocketAddress inetSocketAddress = resolver.resolve(exchange);
        logger.trace("inetSocketAddress {}", inetSocketAddress);
        logger.trace(".getHostName() {}", inetSocketAddress.getHostName());
        return Mono.just(inetSocketAddress.getHostName());
    };