From a28f05c145fed9c3cfb5e58911a414397d507c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Sat, 31 May 2025 00:08:14 +0800 Subject: [PATCH] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20=E5=9C=B0=E5=9D=80?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E5=B7=A5=E5=85=B7=E7=B1=BB=E6=8A=A5=E9=94=99?= =?UTF-8?q?#ICBHUQ?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/common/core/utils/NetUtils.java | 84 +++++++++++++++++++ .../common/core/utils/ip/AddressUtils.java | 53 ++++++++++-- 2 files changed, 129 insertions(+), 8 deletions(-) create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/NetUtils.java diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/NetUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/NetUtils.java new file mode 100644 index 00000000..72fdf403 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/NetUtils.java @@ -0,0 +1,84 @@ +package org.dromara.common.core.utils; + +import cn.hutool.core.lang.PatternPool; +import cn.hutool.core.net.NetUtil; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.utils.regex.RegexUtils; + +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * 增强网络相关工具类 + * + * @author 秋辞未寒 + */ +@Slf4j +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class NetUtils extends NetUtil { + + /** + * 判断是否为IPv6地址 + * + * @param ip IP地址 + * @return 是否为IPv6地址 + */ + public static boolean isIPv6(String ip) { + try { + // 判断是否为IPv6地址 + return InetAddress.getByName(ip) instanceof Inet6Address; + } catch (UnknownHostException e) { + return false; + } + } + + /** + * 判断IPv6地址是否为内网地址 + *

+ * 以下地址将归类为本地地址,如有业务场景有需要,请根据需求自行处理: + *
+     * 通配符地址 0:0:0:0:0:0:0:0
+     * 链路本地地址 fe80::/10
+     * 唯一本地地址 fec0::/10
+     * 环回地址 ::1
+     * 
+ * + * @param ip IP地址 + * @return 是否为内网地址 + */ + public static boolean isInnerIPv6(String ip) { + try { + // 判断是否为IPv6地址 + if (InetAddress.getByName(ip) instanceof Inet6Address inet6Address) { + // isAnyLocalAddress 判断是否为通配符地址,通常不会将其视为内网地址,根据业务场景自行处理判断 + // isLinkLocalAddress 判断是否为链路本地地址,通常不算内网地址,是否划分归属于内网需要根据业务场景自行处理判断 + // isLoopbackAddress 判断是否为环回地址,与IPv4的 127.0.0.1 同理,用于表示本机 + // isSiteLocalAddress 判断是否为本地站点地址,IPv6唯一本地地址(Unique Local Addresses,简称ULA) + if (inet6Address.isAnyLocalAddress() + || inet6Address.isLinkLocalAddress() + || inet6Address.isLoopbackAddress() + || inet6Address.isSiteLocalAddress()) { + return true; + } + } + } catch (UnknownHostException e) { + // 注意,isInnerIPv6方法和isIPv6方法的适用范围不同,所以此处不能忽略其异常信息。 + throw new IllegalArgumentException("Invalid IPv6 address!", e); + } + return false; + } + + /** + * 判断是否为IPv4地址 + * + * @param ip IP地址 + * @return 是否为IPv4地址 + */ + public static boolean isIPv4(String ip) { + return RegexUtils.isMatch(PatternPool.IPV4, ip); + } + +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ip/AddressUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ip/AddressUtils.java index 3f7cd57a..2fe3bd7b 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ip/AddressUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ip/AddressUtils.java @@ -1,11 +1,11 @@ package org.dromara.common.core.utils.ip; -import cn.hutool.core.net.NetUtil; import cn.hutool.http.HtmlUtil; -import org.dromara.common.core.utils.StringUtils; import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.dromara.common.core.utils.NetUtils; +import org.dromara.common.core.utils.StringUtils; /** * 获取地址类 @@ -16,18 +16,55 @@ import lombok.extern.slf4j.Slf4j; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class AddressUtils { + // 未知IP + public static final String UNKNOWN_IP = "XX XX"; + // 内网地址 + public static final String LOCAL_ADDRESS = "内网IP"; // 未知地址 - public static final String UNKNOWN = "XX XX"; + public static final String UNKNOWN_ADDRESS = "未知"; public static String getRealAddressByIP(String ip) { - if (StringUtils.isBlank(ip)) { - return UNKNOWN; + // 处理空串并过滤HTML标签 + ip = HtmlUtil.cleanHtmlTag(StringUtils.blankToDefault(ip,"")); + // 判断是否为IPv4 + if (NetUtils.isIPv4(ip)) { + return resolverIPv4Region(ip); } + // 判断是否为IPv6 + if (NetUtils.isIPv6(ip)) { + return resolverIPv6Region(ip); + } + // 如果不是IPv4或IPv6,则返回未知IP + return UNKNOWN_IP; + } + + /** + * 根据IPv4地址查询IP归属行政区域 + * @param ip ipv4地址 + * @return 归属行政区域 + */ + private static String resolverIPv4Region(String ip){ // 内网不查询 - ip = StringUtils.contains(ip, "0:0:0:0:0:0:0:1") ? "127.0.0.1" : HtmlUtil.cleanHtmlTag(ip); - if (NetUtil.isInnerIP(ip)) { - return "内网IP"; + if (NetUtils.isInnerIP(ip)) { + return LOCAL_ADDRESS; } return RegionUtils.getCityInfo(ip); } + + /** + * 根据IPv6地址查询IP归属行政区域 + * @param ip ipv6地址 + * @return 归属行政区域 + */ + private static String resolverIPv6Region(String ip){ + // 内网不查询 + if (NetUtils.isInnerIPv6(ip)) { + return LOCAL_ADDRESS; + } + log.warn("ip2region不支持IPV6地址解析:{}", ip); + // 不支持IPv6,不再进行没有必要的IP地址信息的解析,直接返回 + // 如有需要,可自行实现IPv6地址信息解析逻辑,并在这里返回 + return UNKNOWN_ADDRESS; + } + }