1. ip2region 简介
ip2region 是一个离线ip地址定位库和ip定位数据管理框架,能实现10微秒级别的查询效率,提供了众多主流编程语言的xdb数据生成和查询客户端实现。
每个 ip 数据段的 region 信息都固定了格式:国家|区域|省份|城市|isp,只有中国的数据绝大部分精确到了城市,其他国家部分数据只能定位到国家,后前的选项全部是0。
2. 使用步骤
2.1 下载资源
下载 ip2region 后,将ip2region.xdb (如下图)复制到项目的resources/ipdb
文件夹下。
2.2 引入依赖
<dependency> <groupid>org.lionsoul</groupid> <artifactid>ip2region</artifactid> <version>2.6.5</version> </dependency>
2.3 编写工具类
2.3.1 获取 ip 地址
根据用户请求获取用户真实 ip 地址:
/** * 在 nginx 等代理之后获取用户真实 ip 地址 * @return 用户的真实 ip 地址 */ public static string getipaddress(httpservletrequest request) { if (request == null) { return null; } string ip = request.getheader("x-forwarded-for"); if (isipaddress(ip)) { ip = request.getheader("proxy-client-ip"); } if (isipaddress(ip)) { ip = request.getheader("wl-proxy-client-ip"); } if (isipaddress(ip)) { ip = request.getheader("http_client_ip"); } if (isipaddress(ip)) { ip = request.getheader("http_x_forwarded_for"); } if (isipaddress(ip)) { ip = request.getremoteaddr(); if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) { //根据网卡取本机配置的ip try { inetaddress inet = inetaddress.getlocalhost(); ip = inet.gethostaddress(); } catch (unknownhostexception e) { e.printstacktrace(); } } } return ip; }
如果有使用 nginx 等代理服务器则需进行配置[云笔记系统没有配置也可以正常使用],例如在nginx.conf
文件中进行如下配置:
location / { proxy_set_header host $http_host; proxy_set_header x-real-ip $remote_addr; proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for; proxy_set_header x-forwarded-proto $scheme; }
其中
- host:获取客户端(client)的真实域名和端口号
- x-real-ip:获取客户端真实 ip 地址
- x-forwarded-for:也是获取客户端真实 ip 地址,如果有多层代理时会获取客户端真实 ip 及每层代理服务器的 ip 地址
- x-forwarded-proto:获取客户端的真实协议(如 http、https)
getremoteaddr()
用于获取没有代理服务器情况下用户的 ip 地址- 当用户的请求经过一个代理服务器后到达最终服务器,此时在最终服务器端通过
getremoteaddr()
只能得到代理服务器的 ip 地址,通过在代理服务器中配置proxy_set_header x-real-ip $remote_addr
,最终的服务器可以通过x-real-ip
获取用户的真实 ip 地址。 - 当用户的请求经过多个代理服务器后到达最终服务器时,配置
proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for
后可通过x-forwarded-for
获取用户真实 ip 地址(请求通过第一台 nginx时:x-forwarded-for = x-real-ip = 用户真实 ip 地址;请求通过第二台 nginx 时:x-forwarded-for = 用户真实 ip 地址, x-real-ip = 上一台 nginx 的 ip 地址 )。 - 获取客户端的ip地址不仅可以通过
proxy_set_header x-real-ip $remote_addr;
获取,也可以通过proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for;
获取。
2.3.2 根据 ip 地址获取 ip 归属地
/** * 根据 ip 地址返回归属地,国内返回但省份,国外返回到国家 * @param ip ip 地址 * @return ip 归属地 */ public static string getipregion(string ip) { initip2regionresource(); hashmap<string, string> cityinfo = new hashmap<>(); string searchipinfo = getcityinfo(ip); //------------------------------------------------------- //searchipinfo 的数据格式: 国家|区域|省份|城市|isp //192.168.31.160 0|0|0|内网ip|内网ip //47.52.236.180 中国|0|香港|0|阿里云 //220.248.12.158 中国|0|上海|上海市|联通 //164.114.53.60 美国|0|华盛顿|0|0 //------------------------------------------------------- string[] splitipinfo = searchipinfo.split("\\|"); cityinfo.put("ip",ip); cityinfo.put("searchinfo", searchipinfo); cityinfo.put("country",splitipinfo[0]); cityinfo.put("region",splitipinfo[1]); cityinfo.put("province",splitipinfo[2]); cityinfo.put("city",splitipinfo[3]); cityinfo.put("isp",splitipinfo[3]); //--------------国内属地返回省份-------------- if ("中国".equals(cityinfo.get("country"))){ return cityinfo.get("province"); } //------------------内网 ip---------------- if ("0".equals(cityinfo.get("country"))){ if ("内网ip".equals(cityinfo.get("isp"))){ return ""; } else return ""; } //--------------国外属地返回国家-------------- else { return cityinfo.get("country"); } }
2.3.3 完整代码
iputils.java3:
import org.lionsoul.ip2region.xdb.searcher; import org.springframework.core.io.classpathresource; import org.springframework.stereotype.component; import org.springframework.util.filecopyutils; import javax.annotation.postconstruct; import javax.servlet.http.httpservletrequest; import java.io.inputstream; import java.net.inetaddress; import java.net.unknownhostexception; import java.util.hashmap; @component public class iputils { private static searcher searcher; /** * 在 nginx 等代理之后获取用户真实 ip 地址 * @return 用户的真实 ip 地址 */ public static string getipaddress(httpservletrequest request) { if (request == null) { return null; } string ip = request.getheader("x-forwarded-for"); if (isipaddress(ip)) { ip = request.getheader("proxy-client-ip"); } if (isipaddress(ip)) { ip = request.getheader("wl-proxy-client-ip"); } if (isipaddress(ip)) { ip = request.getheader("http_client_ip"); } if (isipaddress(ip)) { ip = request.getheader("http_x_forwarded_for"); } if (isipaddress(ip)) { ip = request.getremoteaddr(); if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) { //根据网卡取本机配置的ip try { inetaddress inet = inetaddress.getlocalhost(); ip = inet.gethostaddress(); } catch (unknownhostexception e) { e.printstacktrace(); } } } return ip; } /** * 判断是否为 ip 地址 * @param ip ip 地址 */ public static boolean isipaddress(string ip) { return ip == null || ip.length() == 0 || "unknown".equalsignorecase(ip); } /** * 获取本地 ip 地址 * @return 本地 ip 地址 */ public static string gethostip() { try { return inetaddress.getlocalhost().gethostaddress(); } catch (unknownhostexception e) { e.printstacktrace(); } return "127.0.0.1"; } /** * 获取主机名 * @return 本地主机名 */ public static string gethostname() { try { return inetaddress.getlocalhost().gethostname(); } catch (unknownhostexception e) { e.printstacktrace(); } return "未知"; } /** * 根据 ip 地址从 ip2region.db 中获取地理位置 * @param ip ip 地址 * @return ip归属地 */ public static string getcityinfo(string ip) { try { return searcher.search(ip); } catch (exception e) { e.printstacktrace(); } return null; } /** * 在服务启动时加载 ip2region.db 到内存中 * 解决打包 jar 后找不到 ip2region.db 的问题 * @throws exception 出现异常应该直接抛出终止程序启动,避免后续 invoke 时出现更多错误 */ @postconstruct private static void initip2regionresource() { try { inputstream inputstream = new classpathresource("/ipdb/ip2region.xdb").getinputstream(); byte[] dbbinstr = filecopyutils.copytobytearray(inputstream); // 创建一个完全基于内存的查询对象 searcher = searcher.newwithbuffer(dbbinstr); } catch (exception e) { e.printstacktrace(); } } /** * 根据 ip 地址返回归属地,国内返回但省份,国外返回到国家 * @param ip ip 地址 * @return ip 归属地 */ public static string getipregion(string ip) { initip2regionresource(); hashmap<string, string> cityinfo = new hashmap<>(); string searchipinfo = getcityinfo(ip); //------------------------------------------------------- //searchipinfo 的数据格式: 国家|区域|省份|城市|isp //192.168.31.160 0|0|0|内网ip|内网ip //47.52.236.180 中国|0|香港|0|阿里云 //220.248.12.158 中国|0|上海|上海市|联通 //164.114.53.60 美国|0|华盛顿|0|0 //------------------------------------------------------- string[] splitipinfo = searchipinfo.split("\\|"); cityinfo.put("ip",ip); cityinfo.put("searchinfo", searchipinfo); cityinfo.put("country",splitipinfo[0]); cityinfo.put("region",splitipinfo[1]); cityinfo.put("province",splitipinfo[2]); cityinfo.put("city",splitipinfo[3]); cityinfo.put("isp",splitipinfo[3]); //--------------国内属地返回省份-------------- if ("中国".equals(cityinfo.get("country"))){ return cityinfo.get("province"); } //------------------内网 ip---------------- if ("0".equals(cityinfo.get("country"))){ if ("内网ip".equals(cityinfo.get("isp"))){ return ""; } else return ""; } //--------------国外属地返回国家-------------- else { return cityinfo.get("country"); } } }
2.4 结果测试
测试代码:
@test public void test04(){ system.out.println(iputils.getipregion("117.28.182.162")); }
测试结果:
福建省
到此这篇关于java使用ip2region获取用户的ip归属地的详细步骤的文章就介绍到这了,更多相关java ip2region获取ip归属地内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论