最近的一个项目的某个功能获取用户的ip地址,添加用户的系统使用记录。

  我发现当我直接使用getRemoteAddr()方法从HttpServletRequet中获取用户的ip时,获取到的是服务器的ip地址,为什么会这样呢?


 

网上找到的答案

    “当我们通过request获取客户端IP时,自身服务器通常会为了保护信息或者负载均衡的目的,对自身服务器做反向***。此时如果我们通过request.getRemoteAddr();可能获取到的是自身***服务器的IP,而无法达到获取用户请求ip的目的。


 

最终的解决方案

  以下整理了各个***服务器自己开发的转发服务请求头,这些请求头都不是标准的http请求头,不一定所有的***都会带上这些请求头,所以通过这方式只能尽可能的获取到真实ip,但不能保证一定可以获取到真实ip,而且***服务器请求头中获取的ip是可伪造的。

参数:

nginx服务*** X-Real-IP
Squid 服务*** X-Forwarded-For
apache 服务*** Proxy-Client-IP
weblogic 服务*** WL-Proxy-Client-IP
有些***服务器 HTTP_CLIENT_IP

以下是获取用户真实ip的工具类:

package com.pantech.boot.common.systemlog.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * @author 肖政宇
 * @date 2019-10-29 13:41
 * 说明:客户端ip地址相关操作
 */
@Component
public class IpAddress {

    @Autowired
    HttpServletRequest request;

    /**
     * 获取发送请求的客户端的ip地址
     *
     * @param request - 请求头
     * @return - ip地址
     */
    public String getIpAddress(HttpServletRequest request) {
        String ip = null;

        //X-Forwarded-For:Squid 服务***
        String ipAddresses = request.getHeader("X-Forwarded-For");

        //X-Real-IP:nginx服务***
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            ipAddresses = request.getHeader("X-Real-IP");
        }

        //Proxy-Client-IP:apache 服务***
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            ipAddresses = request.getHeader("Proxy-Client-IP");
        }

        //WL-Proxy-Client-IP:weblogic 服务***
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            ipAddresses = request.getHeader("WL-Proxy-Client-IP");
        }

        //HTTP_CLIENT_IP:有些***服务器
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            ipAddresses = request.getHeader("HTTP_CLIENT_IP");
        }

        //有些网络通过多层***,那么获取到的ip就会有多个,一般都是通过逗号(,)分割开来,并且第一个ip为客户端的真实IP
        if (ipAddresses != null && ipAddresses.length() != 0) {
            ip = ipAddresses.split(",")[0];
        }

        //还是不能获取到,最后再通过request.getRemoteAddr();获取
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    public String getIpAddress() {
        return getIpAddress(request);
    }
}

 

文中提到的解决方案原文地址:https://www.cnblogs.com/Mauno/p/Mauno.html