java 服务器获取请求的IP方法之总结

项目中需要和第三方平台接口,加了来源IP鉴权功能,测试时发现没有问题,但是部署以后发现存在问题,一直鉴权不通过,一群人抓瞎。

我找到那块的代码,跟了一遍流程发现逻辑没有啥问题,但是最终的结果却还是鉴权不通过,实在有些诡异。其基本逻辑为先取得配置的IP列表,然后通过request.getRemoteAddr()取得客户端的IP地址,做鉴权和校验,逻辑没问题,那么肯定是request.getRemoteAddr()出了问题,google下,发现有人遇到类似的问题。

最终定位为request.getRemoteAddr()这种方法在大部分情况下都是有效的。但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了。

如果使用了反向代理软件,将http://192.168.1.110:2046/ 的URL反向代理为http://www.xxx.com/ 的URL时,用request.getRemoteAddr()方法获取的IP地址是:127.0.0.1 或 192.168.1.110,而并不是客户端的真实IP。

经过代理以后,由于在客户端和服务之间增加了中间层,因此服务器无法直接拿到客户端的IP,服务器端应用也无法直接通过转发请求的地址返回给客户端。但是在转发请求的HTTP头信息中,增加了X-FORWARDED-FOR信息用以跟踪原有的客户端IP地址和原来客户端请求的服务器地址。

原来如此,我们的项目中正好是有前置apache,将一些请求转发给后端的weblogic,看来就是这样导致的咯。

给出一份还算靠谱的代码

改进后的java代码:

class IpUtils {
	 public static String getIpAddr(HttpServletRequest request) {
	        String ip = request.getHeader("X-Forwarded-For");
	        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	            ip = request.getHeader("Proxy-Client-IP");
	        }
	        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	            ip = request.getHeader("WL-Proxy-Client-IP");
	        }
	        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	            ip = request.getHeader("HTTP_CLIENT_IP");
	        }
	        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
	        }
	        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
	            ip = request.getRemoteAddr();
	        }
	        return ip;
	    }
}

PS:可是,如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串ip值,究竟哪个才是真正的用户端的真实IP呢?
答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。如:X-Forwarded-For:192.168.1.110, 192.168.1.120, 192.168.1.130, 192.168.1.100,用户真实IP为: 192.168.1.110

================================下面是OSC中的=====================================

import javax.servlet.http.HttpServletRequest;
 
import org.apache.log4j.Logger;
 
 
public final class InternetProtocol {
    private static Logger log = Logger.getLogger(InternetProtocol.class);
    /**
     * 构造函数.
     */
    private InternetProtocol() {
    }
 
    /**
     * 获取客户端IP地址.<br>
     * 支持多级反向代理
     * 
     * @param request
     *            HttpServletRequest
     * @return 客户端真实IP地址
     */
    public static String getRemoteAddr(final HttpServletRequest request) {
        try{
            String remoteAddr = request.getHeader("X-Forwarded-For");
            // 如果通过多级反向代理,X-Forwarded-For的值不止一个,而是一串用逗号分隔的IP值,此时取X-Forwarded-For中第一个非unknown的有效IP字符串
            if (isEffective(remoteAddr) && (remoteAddr.indexOf(",") > -1)) {
                String[] array = remoteAddr.split(",");
                for (String element : array) {
                    if (isEffective(element)) {
                        remoteAddr = element;
                        break;
                    }
                }
            }
            if (!isEffective(remoteAddr)) {
                remoteAddr = request.getHeader("X-Real-IP");
            }
            if (!isEffective(remoteAddr)) {
                remoteAddr = request.getRemoteAddr();
            }
            return remoteAddr;
        }catch(Exception e){
            log.error("get romote ip error,error message:"+e.getMessage());
            return "";
        }
    }
     
    /**
     * 获取客户端源端口
     * @param request
     * @return
     */
    public static Long getRemotePort(final HttpServletRequest request){
        try{
            String port = request.getHeader("remote-port");
            if( StringUtil.isNotEmptyString(port )) {
                try{
                    return Long.parseLong(port);
                }catch(NumberFormatException ex){
                    log.error("convert port to long error , port: "+port);
                    return 0l;
                }
            }else{
                return 0l;
            }       
        }catch(Exception e){
            log.error("get romote port error,error message:"+e.getMessage());
            return 0l;
        }
    }
 
    /**
     * 远程地址是否有效.
     * 
     * @param remoteAddr
     *            远程地址
     * @return true代表远程地址有效,false代表远程地址无效
     */
    private static boolean isEffective(final String remoteAddr) {
        boolean isEffective = false;
        if ((null != remoteAddr) && (!"".equals(remoteAddr.trim()))
                && (!"unknown".equalsIgnoreCase(remoteAddr.trim()))) {
            isEffective = true;
        }
        return isEffective;
    }
}
时间: 2024-10-12 06:16:03

java 服务器获取请求的IP方法之总结的相关文章

Java正确获取客户端真实IP方法整理

在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了. 如果使用了反向代理软件,将http://192.168.1.110:2046/的URL反向代理为http://www.abc.com/的URL时,用request.getRemoteAddr()方法获取的IP地址是:127.0.0.1或192.168.1.110,而并不是客户端的真实IP

Java服务器获取客户端的ip

原文:http://www.open-open.com/code/view/1454133120089 /** * 获取登录用户IP地址 * * @param request * @return */ public static String getIpAddr(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() ==

获取当前年月日...信息的方法,获取请求的ip地址,由于数据库中是time格式,所以要获取时分秒的格式

1.获取当前年月日...信息的方法 1 public class CommonDate { 2 3 public final String year = String.valueOf(Calendar.getInstance().get(Calendar.YEAR)); 4 public final String month = String.valueOf(Calendar.getInstance().get(Calendar.MONTH)+1); 5 public final String

Java Web 获取客户端真实IP

Java Web 获取客户端真实IP 发生的场景:服务器端接收客户端请求的时候,一般需要进行签名验证,客户端IP限定等情况,在进行客户端IP限定的时候,需要首先获取该真实的IP.一般分为两种情况: 方式一.客户端未经过代理,直接访问服务器端(nginx,squid,haproxy): 方式二.客户端通过多级代理,最终到达服务器端(nginx,squid,haproxy): 客户端请求信息都包含在HttpServletRequest中,可以通过方法getRemoteAddr()获得该客户端IP.此

nginx做反向负载均衡,后端服务器获取真实客户端ip

开门见山,操作如下: 首先,在前端nginx上需要做如下配置: location / { proxy_pass http://test1; proxy_set_hearder host $host; proxy_set_header X-Real_IP $remoute_addr; proxy_set_header $proxy_add_x_forwarded_for; }; nginx会在把请求转向后台real-server前把http报头中的ip地址进行替换:这样操作完成后,real-ser

获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址

/** * 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址; * @Title: getIpAddress * @Description: TODO(这里用一句话描述这个方法的作用) * @param @param request * @param @return * @param @throws IOException 参数 * @return String 返回类型 * @throws */ public String getIpAddress(HttpServletR

java如何获取本机IP

java如何获取本机IP import java.net.*; public class Test6 { public static void main(String[] args) { // TODO Auto-generated method stub InetAddress ia=null; try { ia=ia.getLocalHost(); String localname=ia.getHostName(); String localip=ia.getHostAddress(); S

web服务器获取请求客户端真实地址的方法

服务器获取客户端或者网页的请求,获取IP时需要注意,因为一个请求到达服务器之前,一般都会经过一层或者多层代理服务器,比如反向代理服务器将http://192.168.1.10:port/ 的URL反向代理为http://www.xxx.com/ 的URL时,用request.getRemoteAddr() 方法获取的IP地址是:127.0.0.1 或 192.168.1.10 ,而并不是客户端的真实IP.但在经过代理服务器之后,请求头中都会多一些字段,我们可以根据这些字段来获取真实的IP而不是经

Java 服务器获取客户端IP

今天做了一个在线投票的项目,具体需求如下 1.不需要用户体系 2.打开网页就可以投票 3.每人每天只可以投1票 根据以上需求,不同客户端只能用ip来区分,便顺便研究了一下java 服务器端获取客户端ip的方式,废话不多说,直接上代码 /** * 获取客户端IP地址 * * @param request * @return */ public static String getIPAddr(HttpServletRequest request) { String ip = request.getH