标签:
若应用部署到服务器端则获取的IP为服务器地址
private static String getWebServerIp() {
StringBuilder ipString = new StringBuilder();
Enumeration<NetworkInterface> netInterfaces = null;
InetAddress ip = null;
try {
netInterfaces = NetworkInterface.getNetworkInterfaces();
while (netInterfaces.hasMoreElements()) {
NetworkInterface ni = netInterfaces.nextElement();
Enumeration<InetAddress> ips = ni.getInetAddresses();
while (ips.hasMoreElements()) {
ip = ips.nextElement();
if (ip != null && !ip.isLoopbackAddress()) {
if (ip.getHostAddress() != null && ip.getHostAddress().indexOf(":") < 0) {
ipString.append(ip.getHostAddress()).append(" ");
}
}
}
}
} catch (Exception e) {
log.error("get local ip error", e);
}
return ipString.toString();
}
2:获取用户真实Ip
public class GetIpAction extends BaseAction {
public String getRemoteIpNew() {
Result result = new Result();
if (request == null) {
return null;
}
/** * 来源1 用于使用反向代理的运行环境,如生产,测试
* 来源2 用于本机开发环境
*/
String ip = null;
// 来源1 优先从x-forwarded-for 中抓取ip
String ipOld = request.getHeader("j-forwarded-for");
System.out.println("IpWebUtils->getRemoteIpNew j-forwarded-for:" + ipOld);
if (ipOld == null || ipOld.length() == 0 || "unknown".equalsIgnoreCase(ipOld)) {
ipOld = request.getHeader("x-forwarded-for");
System.out.println("IpWebUtils->getRemoteIpNew x-forwarded-for:" + ipOld);
}
if (StringUtils.isBlank(ipOld) || "unknown".equalsIgnoreCase(ipOld)) {
//来源2 ,开发环境使用
ipOld = request.getRemoteAddr();
System.out.println("IpWebUtils->getRemoteIpNew getRemoteAddr:" + ipOld);
}
if (ipOld.contains(",")) {
//使用代理的情况,如 12.113.55.66,15.23.41.52
String proxyIp[] = ipOld.split(",");
//1.使用代理的正常情况,xff结构为 [用户ip,proxy1,proxy2,...proxyN,loadbalanceIp]
//2.xff伪造的可能情况 [proxy1,proxy2,...proxyN,用户ip,loadbalanceIp]
//3. 从后向前抓取第一个外网ip作为用户ip
//4. 为防止xff伪造攻击, 可能造成部分使用代理的用户出现验证码
for (int i = proxyIp.length - 1; i >= 0; i--) {
String tempIp = proxyIp[i];
if (!inLAN(tempIp)) {
//第一个非局域网ip作为用户ip
ip = tempIp;
break;
}
}
if (ip == null) {
//全部ip均为内网ip取第一个内网ip作为用户ip
ip = proxyIp[0];
}
} else {
ip = ipOld;
}
ip = ip.trim();
//有些变态的情况带着端口
result.addDefaultModel("message", ip);
//return ip.contains(":") ? ip.split(":")[0] : ip;
toVm(result);
return SUCCESS;
}
该函数通过分析获取到不同种类的Ip字符串(通过Http请求头获取)来区分不同种类的网络模型。
以下两个方法为上述函数中用到的方法。
1:判断获取到的地址为哪种类型的Ip格式。
private static boolean inLAN(String tempId) {
tempId = StringUtils.trimToEmpty(tempId);
int[] ints = divideIp(tempId); //非法ip
if (ints.length < 4) {
return true;
}
if (ints[0] == 10) { //a类ip
return true;
}
if (ints[0] == 192 && ints[1] == 168 && ints[2] >= 0 && ints[2] <= 255) {
//c类ip
return true; }
if (ints[0] == 172 && ints[1] >= 16 && ints[1] <= 31) {
//b类ip
return true; }
if ("127.0.0.1".equals(tempId)) {
//本机地址
return true;
}
return false;
}
2.拆分获取到的Ip字符串
private static int[] divideIp(String tempId) {
String[] strs = tempId.split("\\.");
int[] result = new int[strs.length];
for (int i = 0; i < strs.length; i++) {
try {
result[i] = Integer.parseInt(StringUtils.trimToEmpty(strs[i]));
} catch (Exception e) {
}
}
return result;
}
此种方法部署到测试环境中时,获取到的Ip地址均为同一个地址。由于不能实际验证,怀疑获取到的Ip地址为内网访问处于外网测试环境服务器的Ip。访问测试环境需要通过地址转换,所有访问测试环境服务器的Ip均被替换成同样的一个Ip。该问题在将代码上线后不存在。
上线后获取的x-forward-for Ip地址为用户真实Ip地址,两个proxy代理地址均为Null,remote-Ip为127.0.0.1。
具体为什么会这样原因还不是十分清楚,欢迎大神指导讨论。
标签:
原文地址:http://www.cnblogs.com/Isaca/p/4833392.html