解决Docker内的服务无法获取请求真实IP问题

概要

一般我们的server运行在docker内,web服务通过Nginx反向代理(Nginx运行在docker内),因此客户端并不是直接访问到服务端的,而是客户端首先请求到反向代理,反向代理再转发到服务端实现服务访问,通过反向代理实现路由/负载均衡等策略。这样一来在服务端拿到的客户端IP将是反向代理IP,而不是真实客户端IP,所以需要一种办法来获取到真实客户端IP。

技术细节

nginx配置文件

server {
    listen       80;
    server_name  localhost;
    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;
    
    location / {
        root   /web;
        index  index.html index.htm;
    }
    
    #error_page  404              /404.html;
    
    # redirect server error pages to the static page /50x.html
    #
    
    location /api/ {
        proxy_pass   http://base-framework-server/;
        #下边是为获取真实IP所做的设置
        proxy_set_header    X-Real-IP        $remote_addr;
        proxy_set_header    X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_set_header    HTTP_X_FORWARDED_FOR $remote_addr;
        proxy_set_header    X-Forwarded-Proto $scheme;
        proxy_redirect      default;
		}
}

代码获取IP地址

private static final String UNKNOWN  = "unknown";
private String getIpAddress(ServerHttpRequest request) {
            org.springframework.http.HttpHeaders headers = request.getHeaders();
        String ip = headers.getFirst("x-forwarded-for");
        if (ip != null && ip.length() != 0 && !UNKNOWN.equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个ip值,第一个ip才是真实ip
            if (ip.contains(",")) {
                ip = ip.split(",")[0];
            }
        }
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = headers.getFirst("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = headers.getFirst("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = headers.getFirst("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = headers.getFirst("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = headers.getFirst("X-Real-IP");
        }
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = Objects.requireNonNull(request.getRemoteAddress()).getAddress().getHostAddress();
        }
        return ip;
    }

小结

本文主要处理Docker容器化部署服务方式,服务端无法从请求中获取真实IP的案例,具体解决手段通过修改nginx配置文件,再通过代码获取请求头中的参数来获取IP地址。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图个吉利儿

欢迎大家一起学习!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值