getHeader("x-forwarded-for")获取真实IP

 在很多应用下都可能有需要将用户的真实IP记录下来,这时就要获得用户的真实IP地址,在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的。但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了。


  1.经过反向代理软件后如何得到用户真实的ip

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

  获取用户真实的ip,可以通过以下两种方法中的一种

  1)

   

public String getRemortIP(HttpServletRequest request) {  
    if (request.getHeader("x-forwarded-for") == null) {  
        return request.getRemoteAddr();  
    }  
    return request.getHeader("x-forwarded-for");  
}

2)

public  String getRemortIP1(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.getRemoteAddr();
				    }  
			    }  
		    }else{
		    	String[] ipArray = ip.split(",", 100);
		    	if(ipArray != null && ipArray.length > 1){
		    		ip = ipArray[0];
		    	}
		    }
		    return ip;  
		 
	}

如果通过了多级反向代理的话,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


2.通过nginx转发的tomcat如何得到用户真实的ip

经过nginx转发的tomcat,根据上面的方法得到是nginx的ip,而不是用户真实的ip.如果想得到用户真是的ip,那么必须改nginx的配置文件

server {
        listen       80;
        server_name  price.kuche.com;
        location / {
            root   html;
          proxy_set_header  X-Real-IP  $remote_addr;
            proxy_pass http:backServers;
         }
   }



JAVA根据IP地址获取详细的地域信息  

       在系统中,网站的头部一般都有显示是哪个城市的,用户进入到网站的首页后,默认城市应该是用户本地的城市信息,例如:北京,网站就要根据你的IP地址的信息,查询数据,获取北京部分的数据,呵呵,当然我可能描述的不是很清楚,但是可以理解成,通过IP地址定位地理信息就行。很多人现在使用以QQ数据库为基础获取地址信息,但不完整、而且不规范。互联网提供很多其他接口可以完成这项功能.

          接口如下:

通过淘宝IP地址库获取IP位置

1. 请求接口(GET):http://ip.taobao.com/service/getIpInfo.php?ip=[ip地址字串]
2. 响应信息:(json格式的)国家、省(自治区或直辖市)、市(县)、运营商
3. 返回数据格式:
{"code":0,"data":{"ip":"210.75.225.254","country":"\u4e2d\u56fd","area":"\u534e\u5317",
"region":"\u5317\u4eac\u5e02","city":"\u5317\u4eac\u5e02","county":"","isp":"\u7535\u4fe1",
"country_id":"86","area_id":"100000","region_id":"110000","city_id":"110000",
"county_id":"-1","isp_id":"100017"}}
其中code的值的含义为,0:成功,1:失败。
 
新浪的接口 :http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=json&ip=218.192.3.42
返回值
var remote_ip_info ={"ret":1,"start":"218.192.0.0","end":"218.192.7.255","country":"\u4e2d\u56fd","province":"\u5e7f\u4e1c","city":"\u5e7f\u5dde","district":"","isp":"\u6559\u80b2\u7f51","type":"\u5b66\u6821","desc":"\u5e7f\u5dde\u5927\u5b66\u7eba\u7ec7\u670d\u88c5\u5b66\u9662"};

 


import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
 
public classIptoCityUtils {
   
  
    public static String Iptocity (String ip){
         
        Stringaddress = "北京市";
        try {
            address= getAddresses("ip="+ip,"utf-8");
        }catch(UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       
      return address;
    }
   
   
   
     /**
      *
      * @param content
      *           请求的参数格式为:name=xxx&pwd=xxx
      * @param encoding
      *           服务器端请求编码。如GBK,UTF-8等
      * @return
      * @throws UnsupportedEncodingException
      */
     public  static String getAddresses(String content,String encodingString)
       throws UnsupportedEncodingException {
      // 这里调用pconline的接口
      try {
        String urlStr = "http://ip.taobao.com/service/getIpInfo.php";
          // 从http://whois.pconline.com.cn取得IP所在的省市区信息
          String returnStr = getResult(urlStr,content, encodingString);
          System.out.println("returnStr="+returnStr);
          if (returnStr !=null) {
           // 处理返回的省市区信息
           System.out.println(returnStr);
           String[] temp = returnStr.split(",");
           if(temp.length<3){
            return"0";//无效IP,局域网测试
           }
         
          String region="北京市";
       
           if((temp[7].split(":"))[1].replaceAll("\"","") != null &&(temp[7].split(":"))[1].replaceAll("\"","").length() != 0){
              // System.out.println("hellolulu");
                region =(temp[7].split(":"))[1].replaceAll("\"","");
              //  System.out.println("helloluluregion="+region);
             // System.out.println("region="+ ((temp[7].split(":"))[1]));
               region = decodeUnicode(region);//城市
             //  System.out.println("hello lulu1region="+(temp[7].split(":"))[1].replaceAll("\"","").length());
           }
         
         
           return region;
          }
         
    }catch(Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
      return "北京市";
 }
     /**
      * @param urlStr
      *           请求的地址
      * @param content
      *           请求的参数格式为:name=xxx&pwd=xxx
      * @param encoding
      *           服务器端请求编码。如GBK,UTF-8等
      * @return
      */
     public staticString getResult(String urlStr, String content, String encoding) {
      URL url = null;
      HttpURLConnection connection = null;
      try {
       url = new URL(urlStr);
       connection = (HttpURLConnection)url.openConnection();//新建连接实例
       connection.setConnectTimeout(2000);//设置连接超时时间,单位毫秒
       connection.setReadTimeout(2000);//设置读取数据超时时间,单位毫秒
       connection.setDoOutput(true);//是否打开输出流 true|false
       connection.setDoInput(true);//是否打开输入流true|false
       connection.setRequestMethod("POST");//提交方法POST|GET
       connection.setUseCaches(false);//是否缓存true|false
       connection.connect();// 打开连接端口
       DataOutputStream out = newDataOutputStream(connection
         .getOutputStream());// 打开输出流往对端服务器写数据
       out.writeBytes(content);// 写数据,也就是提交你的表单 name=xxx&pwd=xxx
       out.flush();// 刷新
       out.close();// 关闭输出流
       BufferedReader reader = new BufferedReader(new InputStreamReader(
         connection.getInputStream(), encoding));//往对端写完数据对端服务器返回数据
       // ,以BufferedReader流来读取
       StringBuffer buffer = new StringBuffer();
       String line = "";
       while ((line = reader.readLine()) !=null) {
        buffer.append(line);
       }
       reader.close();
       return buffer.toString();
      } catch (IOException e) {
       e.printStackTrace();
      } finally {
       if (connection !=null) {
        connection.disconnect();// 关闭连接
       }
      }
      return null;
     }
     /**
      * unicode 转换成中文
      *
      * @authorfanhui 2007-3-15
      * @param theString
      * @return
      */
     public staticString decodeUnicode(String theString) {
      char aChar;
      int len = theString.length();
      StringBuffer outBuffer = new StringBuffer(len);
      for (intx = 0; x < len;) {
       aChar = theString.charAt(x++);
       if (aChar =='\\'){
        aChar = theString.charAt(x++);
        if (aChar =='u') {
         int value = 0;
         for (int i = 0; i < 4; i++) {
          aChar = theString.charAt(x++);
          switch (aChar) {
          case'0':
          case'1':
          case'2':
          case'3':
          case'4':
          case'5':
          case'6':
          case'7':
          case'8':
          case'9':
           value = (value << 4) + aChar - '0';
           break;
          case'a':
          case'b':
          case'c':
          case'd':
          case'e':
          case'f':
           value = (value << 4) + 10 + aChar- 'a';
           break;
          case'A':
          case'B':
          case'C':
          case'D':
          case'E':
          case'F':
           value = (value << 4) + 10 + aChar- 'A';
           break;
          default:
           throw new IllegalArgumentException(
             "Malformed      encoding.");
          }
         }
         outBuffer.append((char) value);
        } else {
         if (aChar =='t') {
          aChar = '\t';
         } else if (aChar == 'r'){
          aChar = '\r';
         } else if (aChar == 'n'){
          aChar = '\n';
         } else if (aChar == 'f'){
          aChar = '\f';
         }
         outBuffer.append(aChar);
        }
       } else {
        outBuffer.append(aChar);
       }
      }
      return outBuffer.toString();
     }
     
     public staticvoidmain(String args[]){
        Stringaddress= IptoCityUtils.Iptocity("60.209.19.27");
         System.out.println("city="+address);
         
     }
     
}