前言
最近网站有个新需要,获取用户 ip 所在归属地,于是在网上搜寻了好多材料并胜利实现,其中遇到了不长坑以及胜利解决,现记录下来分享给大家。
筹备
获取 ip 归属地有第三方的也有 Java 版本的实现,大家能够依据本人理论状况来实现。
1、第三方 API 查问实现(第三方实现前提是要晓得具体的 IP)。
2、Java 实现(本文就是应用 Java 来实现的)。
Java 实现
我应用的是 ip2region 来实现的,这里留神一下,ip2region 老版本是应用.db 库,而新版本应用的是.xdb 库,具体区别这里有个文章能够看看。
1、下载.xdb 数据库,并保留到 /src/resources 目录下
2、引入 ip2region 包依赖
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
<version>2.7.0</version>
</dependency>
3、获取 ip 地址
这里咱们应用 X-Forwarded-For
来获取客户端的 ip,如下所示:
IpUtils.java
public static String getIpAddr(ServerHttpRequest request){
String ipAddress = null;
try {List<String> xForwardedForHeader = request.getHeaders().get("X-Forwarded-For");
log.info("----------- xForwardedForHeader={}", xForwardedForHeader);
if (xForwardedForHeader != null && !xForwardedForHeader.isEmpty()) {ipAddress = xForwardedForHeader.get(0);
if(ipAddress.indexOf(",") != -1) {ipAddress = ipAddress.split(",")[0];
}
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {List<String> proxyClientIPHeader = request.getHeaders().get("Proxy-Client-IP");
ipAddress = (proxyClientIPHeader != null && !proxyClientIPHeader.isEmpty()) ? proxyClientIPHeader.get(0) : null;
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {List<String> wlProxyClientIPHeader = request.getHeaders().get("WL-Proxy-Client-IP");
ipAddress = (wlProxyClientIPHeader != null && !wlProxyClientIPHeader.isEmpty()) ? wlProxyClientIPHeader.get(0) : null;
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {List<String> httpClientIPHeader = request.getHeaders().get("HTTP_CLIENT_IP");
ipAddress = (httpClientIPHeader != null && !httpClientIPHeader.isEmpty()) ? httpClientIPHeader.get(0) : null;
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {ipAddress = request.getRemoteAddress().getAddress().getHostAddress();
}
}catch (Exception e) {log.error("IPUtils ERROR",e);
}
return ipAddress;
}
4、解析 ip 归属地
有了 ip,咱们应用 ip2region
来解析 ip 归属地,如下所示:
public static byte[] toByteArray(InputStream is) throws IOException {ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {baos.write(buffer, 0, len);
}
return baos.toByteArray();}
// 搜寻 ip 地址
public String searchIpAddr(ServerHttpRequest request){String ip = IpUtils.getIpAddr(request);
log.info("---------ip={}", ip);
Searcher searcher = null;
try {InputStream fileStream = new ClassPathResource("ipdb/ip2region.xdb").getInputStream();
searcher = Searcher.newWithBuffer(toByteArray(fileStream));
} catch (IOException e) {return "";}
try {String region = searcher.search(ip);
searcher.close();
return region;
} catch (Exception e) { }
return "";
}
这段代码须要留神两点:
1、肯定要应用 ClassPathResource("ipdb/ip2region.xdb").getInputStream()
获取文件地位,否则获取不到文件 。
2、将文件流转换成 byte[],而后应用Searcher.newWithBuffer
来解析 ip 归属地。
实现之后,咱们通过 k8s 公布到生产试试看看可不可以拿到 ip 归属地region
,如下所示:
IP 属地:中国 |0| 江苏省 | 南京市 | 电信
总结
1、留神本地的 ip 是 127.0.0.1。
2、接下来我再写一篇文章对于 next.js 遇到的获取不到实在 Ip 问题。
援用
手把手教你用 Java 获取 IP 归属地