|
/** * 獲取真實(shí)IP * @param request * @return */ public static String getRealIp(HttpServletRequest request){ /* 目前網(wǎng)上流行的所謂“取真實(shí)IP地址”的方法,都有bug,沒有考慮到多層透明代理的情況。 多數(shù)代碼類似: string IpAddress = (HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]!=null && HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] !=String.Empty) HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"] :HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]; 事實(shí)上,上面的代碼只試用與用戶只使用了1層代理,如果用戶有2層,3層HTTP_X_FORWARDED_FOR 的值是:“本機(jī)真實(shí)IP,1層代理IP,2層代理IP,.....” , 如果這個(gè)時(shí)候你的數(shù)據(jù)中保存IP字段的長(zhǎng)度很小(15個(gè)字節(jié)),數(shù)據(jù)庫就報(bào)錯(cuò)了。 所以取“真正”IP地址的方式,還應(yīng)該判斷 “HTTP_X_FORWARDED_FOR” 中是否有“,”逗號(hào),或者長(zhǎng)度是否超長(zhǎng)(超過15字節(jié) xxx.xxx.xxx.xxx)。 */ String result = request.getHeader("x-forwarded-for"); if(result!=null&&result.trim().length()>0) { //可能有代理 if(result.indexOf(".")==-1){ //沒有“.”肯定是非IPv4格式 result = null; } else { if(result.indexOf(",")!=-1){ //有“,”,估計(jì)多個(gè)代理。取第一個(gè)不是內(nèi)網(wǎng)的IP。 result = result.trim().replace("'",""); String[] temparyip = result.split(","); for(int i=0;i<temparyip.length;i++){ if(isIPAddress(temparyip[i]) && temparyip[i].substring(0,3)!="10." && temparyip[i].substring(0,7)!="192.168" && temparyip[i].substring(0,7)!="172.16."){ return temparyip[i]; //找到不是內(nèi)網(wǎng)的地址 } } }else if(isIPAddress(result)) {//代理即是IP格式 return result; }else{ result = null; //代理中的內(nèi)容 非IP,取IP } } } if (result== null || result.trim().length()==0){ result = request.getHeader("Proxy-Client-IP"); } if (result== null || result.trim().length()==0){ result = request.getRemoteAddr(); } return result; } /** * 判斷是否是IP地址格式 * @param str1 * @return */ public static boolean isIPAddress(String str1) { // if(str1==null||str1.trim().length()<7||str1.trim().length()>15){ // return false; // } |
|
|