IPUtil

package com.msxf.eyas.common.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.net.*;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public final class IPUtil {
   private IPUtil(){}
   private static final Logger log = LoggerFactory.getLogger(IPUtil.class);
   private static final Map<String, String> subnetMaskMap = new HashMap<String, String>();
   static{
      subnetMaskMap.put("8", "255.0.0.0");
      subnetMaskMap.put("16", "255.255.0.0");
      subnetMaskMap.put("24", "255.255.255.0");
      subnetMaskMap.put("128", "(::1/128");
      subnetMaskMap.put("10", "fe80::203:baff:fe27:1243/10");
   }

   /**
    * 获取客户端IP
    * @see --------------------------------------------------------------------------------------------------
    * @see 1.JSP中获取客户端IP地址的方法是request.getRemoteAddr(),这种方法在大部分情况下都是有效的
    * @see   但是在通过了Apache,Squid等反向代理软件后,获取到的就不是客户端的真实IP地址了
    * @see 2.经过代理后,由于在客户端和服务端之前增加了中间层,因此服务器无法直接拿到客户端IP
    * @see   但在转发请求的HTTP头中增加了X-FORWARDED-FOR,用以跟踪原有的客户端IP地址和原来客户端请求的服务器地址
    * @see 3.经过多级反向代理后,X-FORWARDED-FOR的值就会不止一个,而是一串IP,那么有效IP便是第一个非unknown的字符串
    * @see 更多详细介绍见http://dpn525.iteye.com/blog/1132318
    * @see --------------------------------------------------------------------------------------------------
    */
   public static String getClientIP(HttpServletRequest request){
      String IP = request.getHeader("x-forwarded-for");
      if(null==IP || 0==IP.length() || "unknown".equalsIgnoreCase(IP)){
         IP = request.getHeader("Proxy-Client-IP");
      }
      if(null==IP || 0==IP.length() || "unknown".equalsIgnoreCase(IP)){
         IP = request.getHeader("WL-Proxy-Client-IP");
      }
      if(null==IP || 0==IP.length() || "unknown".equalsIgnoreCase(IP)){
         IP = request.getRemoteAddr();
      }
      //对于通过多个代理的情况,第一个IP为客户端真实IP
      //多个IP会按照','分割('***.***.***.***'.length()=15)
      if(null!=IP && IP.length()>15){
         if(IP.indexOf(",") > 0){
            IP = IP.substring(0, IP.indexOf(","));
         }
      }
      return IP;
   }


   /**
    * 获取客户端IP的另一种写法
    * @see 暂不推荐使用,因为已经有{@link IPUtil#getClientIP(HttpServletRequest)}方法了
    */
   @Deprecated
   public static String getClientIP_(HttpServletRequest request){
      String IP = null;
      Enumeration<String> enu = request.getHeaderNames();
      while(enu.hasMoreElements()){
         String name = enu.nextElement();
         if(name.equalsIgnoreCase("X-Forwarded-For")){
            IP = request.getHeader(name);
         }else if(name.equalsIgnoreCase("Proxy-Client-IP")){
            IP = request.getHeader(name);
         }else if(name.equalsIgnoreCase("WL-Proxy-Client-IP")){
            IP = request.getHeader(name);
         }
         if(null!=IP && 0!=IP.length()){
            break;
         }
      }
      if(null==IP || 0==IP.length()){
         IP = request.getRemoteAddr();
      }
      return IP;
   }


   /**
    * 获取服务器IP的另一种写法
    * @see 暂不推荐使用,因为已经有{@link IPUtil#getServerIP()}方法了
    * @see 另外,对于该方法,单网卡时返回"/192.168.2.173",多网卡时返回"/192.168.2.173/192.168.56.1"
    */
   @Deprecated
   public static String getServerIP_(){
      String serverIP = "";
      try{
         Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
         while(nets.hasMoreElements()){
            NetworkInterface net = nets.nextElement();
            Enumeration<InetAddress> addresses = net.getInetAddresses();
            while(addresses.hasMoreElements()){
               InetAddress IP = addresses.nextElement();
               if(null!=IP && IP instanceof Inet4Address && !IP.getHostAddress().equals("127.0.0.1")){
                  serverIP += IP.toString();
               }
            }
         }
      }catch(SocketException e){
         log.error("服务器IP地址获取失败,堆栈轨迹如下", e);
         serverIP = "服务器IP地址获取失败";
      }
      return serverIP;
   }


   /**
    * 获取服务器IP
    * @see 1.InetAddress.getLocalHost()Windows下能获取到服务器IP,Linux下获取到的就是127.0.0.1
    * @see 2.java.net.InterfaceAddressJDK6.0新增的
    * @see 3.单网卡时会返回其IP,多网卡时会返回第一块网卡的IP
    * @create Aug 28, 2015 5:37:24 PM
    * @author 玄玉<http://blog.csdn.net/jadyer>
    */
   public static String getServerIP(){
      String serverIP = "";
      try{
         Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
         tag:while(nets.hasMoreElements()){
            NetworkInterface net = nets.nextElement();
            if(null != net.getHardwareAddress()){
               List<InterfaceAddress> addressList = net.getInterfaceAddresses();
               for(InterfaceAddress obj : addressList){
                  InetAddress IP = obj.getAddress();
                  if(null!=IP && IP instanceof Inet4Address && !IP.getHostAddress().equals("127.0.0.1")){
                     System.out.println("IP=[" + IP.getHostAddress() +"]的子网掩码为=[" + subnetMaskMap.get(String.valueOf(obj.getNetworkPrefixLength())) + "]");
                     serverIP = IP.getHostAddress();
                     break tag;
                  }
               }
            }
         }
      }catch(SocketException e){
         log.error("服务器IP地址获取失败,堆栈轨迹如下", e);
         serverIP = "服务器IP地址获取失败";
      }
      return serverIP;
   }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值