目录
1. ip2region 简介
2. 使用步骤
2.3.1 获取 IP 地址
2.3.2 根据 IP 地址获取 IP 归属地
2.3.3 完整代码
2.1 下载资源
2.2 引入依赖
2.3 编写工具类
2.4 结果测试
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
文件中进行如下配置1:
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 地址2当用户的请求经过一个代理服务器后到达最终服务器,此时在最终服务器端通过
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;@Componentpublic 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 结果测试
测试代码:
@Testpublic void test04(){ System.out.println(IPUtils.getIpRegion("117.28.182.162"));}
测试结果:
福建省
推荐本站淘宝优惠价购买喜欢的宝贝:
本文链接:https://www.hqyman.cn/post/11003.html 非本站原创文章欢迎转载,原创文章需保留本站地址!


休息一下~~