Ip plugin

This commit is contained in:
hongqiaowei
2023-04-04 14:33:22 +08:00
parent 32e58a2ebf
commit c491f4a93c
8 changed files with 685 additions and 2 deletions

View File

@@ -18,7 +18,7 @@
<spring-session-bom.version>Dragonfruit-SR3</spring-session-bom.version> <spring-session-bom.version>Dragonfruit-SR3</spring-session-bom.version>
<reactor-bom.version>Dysprosium-SR25</reactor-bom.version> <reactor-bom.version>Dysprosium-SR25</reactor-bom.version>
<lettuce.version>5.3.7.RELEASE</lettuce.version> <lettuce.version>5.3.7.RELEASE</lettuce.version>
<netty.version>4.1.90.Final</netty.version> <netty.version>4.1.91.Final</netty.version>
<httpcore.version>4.4.16</httpcore.version> <httpcore.version>4.4.16</httpcore.version>
<log4j2.version>2.17.2</log4j2.version> <log4j2.version>2.17.2</log4j2.version>
<slf4j.version>1.7.36</slf4j.version> <slf4j.version>1.7.36</slf4j.version>

View File

@@ -0,0 +1,148 @@
package com.fizzgate.plugin.ip;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fizzgate.plugin.ip.util.ConfigUtils;
import com.fizzgate.plugin.ip.util.IpMatchUtils;
import com.fizzgate.plugin.ip.util.IpUtils;
import com.fizzgate.plugin.FizzPluginFilter;
import com.fizzgate.plugin.FizzPluginFilterChain;
import com.fizzgate.plugin.auth.ApiConfig;
import com.fizzgate.plugin.auth.ApiConfigService;
import com.fizzgate.util.WebUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import javax.annotation.Resource;
import java.net.SocketException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static com.fizzgate.plugin.ip.RouterConfig.FieldName.*;
/**
* @author hua.huang
*/
@Slf4j
@Component(value = IpPlugin.PLUGIN_NAME)
public class IpPlugin implements FizzPluginFilter {
public static final String PLUGIN_NAME = "fizz_plugin_ip";
@Resource
private ObjectMapper objectMapper;
@Resource
private ApiConfigService apiConfigService;
@Override
@SuppressWarnings("unchecked")
public Mono<Void> filter(ServerWebExchange exchange, Map<String, Object> config) {
RouterConfig routerConfig = routerConfig(exchange, config);
List<PluginConfig.Item> pluginConfigItemList = null;/* pluginConfig(exchange, config); */
if (access(exchange, routerConfig, pluginConfigItemList)) {
log.trace("pass...");
return FizzPluginFilterChain.next(exchange);
}
log.trace("forbidden!");
HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.CONTENT_TYPE, routerConfig.getErrorRespContentType());
return WebUtils.buildDirectResponse(exchange, HttpStatus.FORBIDDEN,
headers, routerConfig.getErrorRespContent());
}
private boolean access(ServerWebExchange exchange,
RouterConfig routerConfig, List<PluginConfig.Item> pluginConfigItemList) {
Set<String> fixedWhiteIpSet = Sets.newHashSet();
Set<String> fixedBlackIpSet = Sets.newHashSet();
ApiConfig apiConfig = apiConfig(exchange);
Set<String> gatewayGroups = (apiConfig == null || apiConfig.gatewayGroups == null) ? Sets.newHashSet() : apiConfig.gatewayGroups;
/* if (!CollectionUtils.isEmpty(pluginConfigItemList)) {
for (PluginConfig.Item fixedConfigItem : pluginConfigItemList) {
if (gatewayGroups.contains(fixedConfigItem.getGwGroup())) {
fixedWhiteIpSet.addAll(IpMatchUtils.ipConfigList(fixedConfigItem.getWhiteIp()));
fixedBlackIpSet.addAll(IpMatchUtils.ipConfigList(fixedConfigItem.getBlackIp()));
}
}
} */
Set<String> whiteIpSet = ConfigUtils.string2set(routerConfig.getWhiteIp());
Set<String> blackIpSet = ConfigUtils.string2set(routerConfig.getBlackIp());
String ip = null;
try {
ip = IpUtils.getServerHttpRequestIp(exchange.getRequest());
} catch (SocketException e) {
log.warn(e.getMessage(), e);
}
log.trace("clientIp:{}, fixedWhiteIpSet:{}, fixedBlackIpSet:{}, whiteIpSet:{}, blackIpSet:{}",
ip, fixedWhiteIpSet, fixedBlackIpSet, whiteIpSet, blackIpSet);
// 未获取到client ip返回false
if (StringUtils.isBlank(ip)) {
return false;
}
// 优先匹配路由级别配置,然后再匹配插件级别配置
// 路由级别白名单匹配到就直接返回true
if (IpMatchUtils.match(ip, whiteIpSet)) {
return true;
}
// 路由级别黑名单匹配到就直接返回false
if (IpMatchUtils.match(ip, blackIpSet)) {
return false;
}
// 插件级别白名单匹配到就直接返回true
/* if (IpMatchUtils.match(ip, fixedWhiteIpSet)) {
return true;
} */
// 插件级别黑名单匹配到就直接返回false
/* if (IpMatchUtils.match(ip, fixedBlackIpSet)) {
return false;
} */
// 路由级别和插件级别都没匹配到
if (CollectionUtils.isEmpty(whiteIpSet) /* || CollectionUtils.isEmpty(fixedWhiteIpSet) */) {
// 都没有配置白名单默认返回true
return true;
} else {
return false;
}
}
private RouterConfig routerConfig(ServerWebExchange exchange, Map<String, Object> config) {
RouterConfig routerConfig = new RouterConfig();
routerConfig.setErrorRespContentType((String) config.getOrDefault(ERROR_RESP_CONTENT_TYPE
, routerConfig.getErrorRespContentType()));
routerConfig.setErrorRespContent((String) config.getOrDefault(ERROR_RESP_CONTENT
, routerConfig.getErrorRespContent()));
routerConfig.setWhiteIp((String) config.getOrDefault(WHITE_IP, StringUtils.EMPTY));
routerConfig.setBlackIp((String) config.getOrDefault(BLACK_IP, StringUtils.EMPTY));
return routerConfig;
}
private List<PluginConfig.Item> pluginConfig(ServerWebExchange exchange, Map<String, Object> config) {
String fixedConfig = (String) config.get(com.fizzgate.plugin.PluginConfig.CUSTOM_CONFIG);
try {
PluginConfig pluginConfig = objectMapper.readValue(fixedConfig, PluginConfig.class);
if (pluginConfig != null && pluginConfig.getConfigs() != null) {
return pluginConfig.getConfigs();
}
} catch (JsonProcessingException e) {
throw new RuntimeException(e.getMessage(), e);
}
return Lists.newArrayList();
}
private ApiConfig apiConfig(ServerWebExchange exchange) {
ServerHttpRequest req = exchange.getRequest();
return apiConfigService.getApiConfig(WebUtils.getAppId(exchange),
WebUtils.getClientService(exchange), req.getMethod(), WebUtils.getClientReqPath(exchange));
}
}

View File

@@ -0,0 +1,18 @@
package com.fizzgate.plugin.ip;
import com.google.common.collect.Lists;
import lombok.Data;
import java.util.List;
@Data
public class PluginConfig {
private List<Item> configs = Lists.newArrayList();
@Data
public static class Item {
private String gwGroup;
private String whiteIp;
private String blackIp;
}
}

View File

@@ -0,0 +1,19 @@
package com.fizzgate.plugin.ip;
import lombok.Data;
import org.springframework.http.MediaType;
@Data
public class RouterConfig {
private String errorRespContentType = MediaType.APPLICATION_JSON_UTF8_VALUE;
private String errorRespContent = "{\"msg\":\"非法IP\",\"code\":-1}";
private String whiteIp;
private String blackIp;
public interface FieldName {
String ERROR_RESP_CONTENT_TYPE = "errorRespContentType";
String ERROR_RESP_CONTENT = "errorRespContent";
String WHITE_IP = "whiteIp";
String BLACK_IP = "blackIp";
}
}

View File

@@ -0,0 +1,36 @@
package com.fizzgate.plugin.ip.util;
import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
import com.google.common.collect.Sets;
import org.apache.commons.lang3.StringUtils;
import java.util.Set;
import java.util.stream.Collectors;
public abstract class ConfigUtils {
public static final String DEFAULT_CHAR_MATCHER_ANY_OF = ",\n";
public static Set<String> string2set(String strVal, String charMatcherAnyOf) {
Set<String> finalSet = Sets.newHashSet();
if (StringUtils.isBlank(strVal)) {
return finalSet;
}
charMatcherAnyOf = StringUtils.isBlank(charMatcherAnyOf) ? DEFAULT_CHAR_MATCHER_ANY_OF : charMatcherAnyOf;
Set<String> set = Sets.newHashSet(
Splitter.on(CharMatcher.anyOf(charMatcherAnyOf)).trimResults().split(strVal));
set = set.stream().filter(StringUtils::isNotBlank).collect(Collectors.toSet());
for (String s : set) {
if (StringUtils.isBlank(s)) {
continue;
}
finalSet.add(StringUtils.trimToEmpty(s));
}
return finalSet;
}
public static Set<String> string2set(String strVal) {
return string2set(strVal, DEFAULT_CHAR_MATCHER_ANY_OF);
}
}

View File

@@ -0,0 +1,271 @@
package com.fizzgate.plugin.ip.util;
import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
import com.google.common.collect.Sets;
import inet.ipaddr.AddressStringException;
import inet.ipaddr.IPAddress;
import inet.ipaddr.IPAddressString;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* ipv4匹配工具
*/
public final class IpMatchUtils {
// IP正则
private static final Pattern IP_PATTERN = Pattern.compile(
"(1\\d{1,2}|2[0-4]\\d|25[0-5]|\\d{1,2})\\." + "(1\\d{1,2}|2[0-4]\\d|25[0-5]|\\d{1,2})\\."
+ "(1\\d{1,2}|2[0-4]\\d|25[0-5]|\\d{1,2})\\." + "(1\\d{1,2}|2[0-4]\\d|25[0-5]|\\d{1,2})");
public static final String DEFAULT_ALLOW_ALL_FLAG = "*";// 允许所有ip标志位
public static final String DEFAULT_DENY_ALL_FLAG = "0"; // 禁止所有ip标志位
private static final String RANGE_SPLITTER = "-"; // ip范围分隔符
/**
* 根据IP白名单设置获取可用的IP列表
*/
public static Set<String> ipConfigList(String allowIp) {
// 拆分出白名单正则
Set<String> set = Sets.newHashSet(Splitter.on(CharMatcher.anyOf(",\n")).trimResults().split(allowIp));
set = set.stream().filter(StringUtils::isNotBlank).collect(Collectors.toSet());
return ipConfigList(Sets.newHashSet(set));
}
/**
* 根据IP白名单设置获取可用的IP列表
*/
public static Set<String> ipConfigList(Set<String> allowIpList) {
Set<String> ipList = new HashSet<>(allowIpList.size());
for (String allow : allowIpList) {
if (allow.contains("*")) { // 处理通配符 *
String[] ips = allow.split("\\.");
String[] from = new String[]{"0", "0", "0", "0"};
String[] end = new String[]{"255", "255", "255", "255"};
List<String> tem = new ArrayList<>();
for (int i = 0; i < ips.length; i++)
if (ips[i].contains("*")) {
tem = complete(ips[i]);
from[i] = null;
end[i] = null;
} else {
from[i] = ips[i];
end[i] = ips[i];
}
StringBuilder fromIP = new StringBuilder();
StringBuilder endIP = new StringBuilder();
for (int i = 0; i < 4; i++) {
if (from[i] != null) {
fromIP.append(from[i]).append(".");
endIP.append(end[i]).append(".");
} else {
fromIP.append("[*].");
endIP.append("[*].");
}
}
fromIP.deleteCharAt(fromIP.length() - 1);
endIP.deleteCharAt(endIP.length() - 1);
for (String s : tem) {
String ip = fromIP.toString().replace("[*]", s.split(";")[0]) + RANGE_SPLITTER
+ endIP.toString().replace("[*]", s.split(";")[1]);
if (validate(ip)) {
ipList.add(ip);
}
}
} else if (allow.contains("/")) { // 处理 网段 xxx.xxx.xxx./24
ipList.add(allow);
} else { // 处理单个 ip 或者 范围
if (validate(allow)) {
ipList.add(allow);
}
}
}
return ipList;
}
/**
* 对单个IP节点进行范围限定
*
* @param arg
* @return 返回限定后的IP范围格式为List[10;19, 100;199]
*/
private static List<String> complete(String arg) {
List<String> com = new ArrayList<>();
int len = arg.length();
if (len == 1) {
com.add("0;255");
} else if (len == 2) {
String s1 = complete(arg, 1);
if (s1 != null) {
com.add(s1);
}
String s2 = complete(arg, 2);
if (s2 != null) {
com.add(s2);
}
} else {
String s1 = complete(arg, 1);
if (s1 != null) {
com.add(s1);
}
}
return com;
}
private static String complete(String arg, int length) {
String from = "";
String end = "";
if (length == 1) {
from = arg.replace("*", "0");
end = arg.replace("*", "9");
} else {
from = arg.replace("*", "00");
end = arg.replace("*", "99");
}
if (Integer.parseInt(from) > 255) {
return null;
}
if (Integer.parseInt(end) > 255) {
end = "255";
}
return from + ";" + end;
}
/**
* 在添加至白名单时进行格式校验
*/
private static boolean validate(String ip) {
String[] temp = ip.split(RANGE_SPLITTER);
for (String s : temp) {
if (!IP_PATTERN.matcher(s).matches()) {
return false;
}
}
return true;
}
/**
* 根据IP,及可用Ip列表来判断ip是否包含在白名单之中
*/
public static boolean match(String ip, Set<String> ipList) {
if (CollectionUtils.isEmpty(ipList)) {
return false;
}
if (ipList.contains(ip)) {
return true;
}
IPAddress ipAddress = null;
try {
ipAddress = new IPAddressString(ip).toAddress();
} catch (AddressStringException e) {
throw new RuntimeException(e);
}
for (String allow : ipList) {
if (allow.contains(RANGE_SPLITTER)) { // 处理 类似 192.168.0.0-192.168.2.1
String[] tempAllow = allow.split(RANGE_SPLITTER);
String[] from = tempAllow[0].split("\\.");
String[] end = tempAllow[1].split("\\.");
String[] tag = ip.split("\\.");
boolean check = true;
for (int i = 0; i < 4; i++) { // 对IP从左到右进行逐段匹配
int s = Integer.parseInt(from[i]);
int t = Integer.parseInt(tag[i]);
int e = Integer.parseInt(end[i]);
if (!(s <= t && t <= e)) {
check = false;
break;
}
}
if (check) {
return true;
}
} else if (allow.contains("/")) { // 处理 网段 xxx.xxx.xxx./24
int splitIndex = allow.indexOf("/");
// 取出子网段
String ipSegment = allow.substring(0, splitIndex); // 192.168.3.0
// 子网数
String netmask = allow.substring(splitIndex + 1); // 24
// ip 转二进制
long ipLong = ipToLong(ip);
// 子网二进制
long maskLong = (2L << 32 - 1) - (2L << (32 - Integer.parseInt(netmask)) - 1);
// ip与和子网相与 得到 网络地址
String calcSegment = longToIP(ipLong & maskLong);
// 如果计算得出网络地址和库中网络地址相同 则合法
if (ipSegment.equals(calcSegment)) {
return true;
}
} else if (allow.contains("*")) {
IPAddress rangeAddress = new IPAddressString(allow).getAddress();
if (rangeAddress.contains(ipAddress)) {
return true;
}
}
}
return false;
}
/**
* 根据IP地址及IP白名单设置规则判断IP是否包含在白名单
*/
public static boolean match(String ip, String ipWhiteConfig) {
if (null == ip || "".equals(ip)) {
return false;
}
// ip格式不对
if (!IP_PATTERN.matcher(ip).matches()) {
return false;
}
if (DEFAULT_ALLOW_ALL_FLAG.equals(ipWhiteConfig)) {
return true;
}
if (DEFAULT_DENY_ALL_FLAG.equals(ipWhiteConfig)) {
return false;
}
Set<String> ipList = ipConfigList(ipWhiteConfig);
return match(ip, ipList);
}
/**
* 将 127.0.0.1形式的IP地址 转换成 10进制整数形式
*/
private static long ipToLong(String strIP) {
long[] ip = new long[4];
// 先找到IP地址字符串中.的位置
int position1 = strIP.indexOf(".");
int position2 = strIP.indexOf(".", position1 + 1);
int position3 = strIP.indexOf(".", position2 + 1);
// 将每个.之间的字符串转换成整型
ip[0] = Long.parseLong(strIP.substring(0, position1));
ip[1] = Long.parseLong(strIP.substring(position1 + 1, position2));
ip[2] = Long.parseLong(strIP.substring(position2 + 1, position3));
ip[3] = Long.parseLong(strIP.substring(position3 + 1));
return (ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3];
}
/**
* 将 10进制整数形式 转换成 127.0.0.1形式的IP地址
*/
private static String longToIP(long longIP) {
// 直接右移24位
return "" + (longIP >>> 24) +
"." +
// 将高8位置0然后右移16位
((longIP & 0x00FFFFFF) >>> 16) +
"." +
((longIP & 0x0000FFFF) >>> 8) +
"." +
(longIP & 0x000000FF);
}
}

View File

@@ -0,0 +1,191 @@
package com.fizzgate.plugin.ip.util;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
import java.net.*;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author huahua
*/
public class IpUtils {
/*
* 取所有IP段的私有IP段
* A类 私有地址 10.0.0.0---10.255.255.255 保留地址 127.0.0.0---127.255.255.255
* B类 私有地址 172.16.0.0-172.31.255.255
* C类 私有地址 192.168.0.0-192.168.255.255
* D类 地址不分网络地址和主机地址
* E类 地址不分网络地址和主机地址
*/
private static long
aBegin = ipToLong("10.0.0.0"),
aEnd = ipToLong("10.255.255.255"),
bBegin = ipToLong("172.16.0.0"),
bEnd = ipToLong("172.31.255.255"),
cBegin = ipToLong("192.168.0.0"),
cEnd = ipToLong("192.168.255.255"),
saveBegin = ipToLong("127.0.0.0"),
saveEnd = ipToLong("127.255.255.255");
// 跟IP有关需要做判断的header参数
private static String
CLIENT_IP = "clientip",
X_FORWARDED_FOR = "x-forwarded-for",
PROXY_CLIENT_IP = "proxy-client-ip",
WL_PROXY_CLIENT_IP = "wl-proxy-client-ip";
private static Set<String> ipHeaderNames = Sets.newHashSet(CLIENT_IP, X_FORWARDED_FOR, PROXY_CLIENT_IP, WL_PROXY_CLIENT_IP);
public static String getServerHttpRequestIp(ServerHttpRequest request) throws SocketException {
// 防止在header中的参数名有大小写之分重新将需要处理的参数值和内容装填入Map中
Map<String, List<String>> ipHeaders = Maps.newHashMap();
Set<Map.Entry<String, List<String>>> headers = request.getHeaders().entrySet();
for (Map.Entry<String, List<String>> header : headers) {
String name = header.getKey();
String lowerCaseName = name.toLowerCase();
if (ipHeaderNames.contains(lowerCaseName)) {
List<String> values = Lists.newArrayList();
for (String headerValue : header.getValue()) {
if (StringUtils.indexOf(headerValue, ",") >= 0) {
String[] headerValueArr = StringUtils.split(headerValue, ",");
if (headerValueArr.length > 0) {
for (String s : headerValueArr) {
values.add(StringUtils.trimToEmpty(s));
}
}
} else {
values.add(headerValue);
}
}
ipHeaders.put(lowerCaseName, values); // 装填key和value
}
}
//取正确的IP
String ipAddress = null;
// 取clientip
List<String> clientIpList = ipHeaders.get(CLIENT_IP); // 取clientip与client-ip有区别
ipAddress = fetchPublicIp(clientIpList);
// 若clientip为空或者是内网IP则取x-forwarded-for
if (StringUtils.isBlank(ipAddress)) {
List<String> xForwardedIpList = ipHeaders.get(X_FORWARDED_FOR);
ipAddress = fetchPublicIp(xForwardedIpList);
}
// 若x-forwarded-for为空则取proxy-client-ip
if (StringUtils.isBlank(ipAddress)) {
List<String> proxyClientIpList = ipHeaders.get(PROXY_CLIENT_IP);
ipAddress = fetchPublicIp(proxyClientIpList);
}
// 若proxy-client-ip为空则取wl-proxy-client-ip
if (StringUtils.isBlank(ipAddress)) {
List<String> wlProxyClientIpList = ipHeaders.get(WL_PROXY_CLIENT_IP);
ipAddress = fetchPublicIp(wlProxyClientIpList);
}
// 若wl-proxy-client-ip为空则取RemoteAddr
if (StringUtils.isBlank(ipAddress)) {
InetSocketAddress inetSocketAddress = request.getRemoteAddress();
if (inetSocketAddress != null) {
InetAddress inetAddress = inetSocketAddress.getAddress();
if (inetAddress instanceof Inet4Address) {
ipAddress = inetAddress.getHostAddress();
}
}
if (StringUtils.equals(ipAddress, "127.0.0.1")) {
// 根据网卡取本机配置的IP
ipAddress = getLocalIp();
}
}
return ipAddress;
}
public static String getLocalIp() throws SocketException {
Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces();
InetAddress ip;
while (allNetInterfaces.hasMoreElements()) {
NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
Enumeration addresses = netInterface.getInetAddresses();
while (addresses.hasMoreElements()) {
ip = (InetAddress) addresses.nextElement();
if (ip instanceof Inet4Address) {
return ip.getHostAddress();
}
}
}
return "";
}
public static long localIpNumber() throws SocketException {
return ipToLong(getLocalIp());
}
private static long ipToLong(String ipAddress) {
long result = 0L;
String[] ipAddressInArray = ipAddress.split("\\.");
if (ipAddressInArray.length != 4) {
return 0;
}
for (int i = 3; i >= 0; i--) {
long ip = 0;
try {
ip = Long.parseLong(ipAddressInArray[3 - i]);
} catch (NumberFormatException e) {
// ignore
}
result |= ip << (i * 8);
}
return result;
}
public static String fetchPublicIp(List<String> ipAddressList) {
String ipAddress = null;
if (ipAddressList == null || ipAddressList.size() <= 0) {
return ipAddress;
}
for (String ip : ipAddressList) {
long ipNum = ipToLong(ip);
if (isIpAddress(ip)
&& !isInner(ipNum, aBegin, aEnd)
&& !isInner(ipNum, bBegin, bEnd)
&& !isInner(ipNum, cBegin, cEnd)
&& !isInner(ipNum, saveBegin, saveEnd)) {
ipAddress = ip;
break;
}
}
return ipAddress;
}
public static boolean isInnerIP(String ipAddress) {
long ipNum = ipToLong(ipAddress);
return isInner(ipNum, aBegin, aEnd) || isInner(ipNum, bBegin, bEnd) || isInner(ipNum, cBegin, cEnd) || isInner(ipNum, saveBegin, saveEnd);
}
private static boolean isInner(long userIp, long begin, long end) {
return (userIp >= begin) && (userIp <= end);
}
/**
* 检验是否是合法的IP地址
*
* @param address String IP地址
* @return boolean IP地址是否合法
*/
public static boolean isIpAddress(String address) {
if (StringUtils.isEmpty(address)) {
return false;
}
String regex = "((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})(\\.((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})){3}";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(address);
return m.matches();
}
}

View File

@@ -10,7 +10,7 @@
<reactor-bom.version>Dysprosium-SR25</reactor-bom.version> <reactor-bom.version>Dysprosium-SR25</reactor-bom.version>
<lettuce.version>5.3.7.RELEASE</lettuce.version> <lettuce.version>5.3.7.RELEASE</lettuce.version>
<nacos.cloud.version>2.2.7.RELEASE</nacos.cloud.version> <nacos.cloud.version>2.2.7.RELEASE</nacos.cloud.version>
<netty.version>4.1.90.Final</netty.version> <netty.version>4.1.91.Final</netty.version>
<httpcore.version>4.4.16</httpcore.version> <httpcore.version>4.4.16</httpcore.version>
<log4j2.version>2.17.2</log4j2.version> <log4j2.version>2.17.2</log4j2.version>
<slf4j.version>1.7.36</slf4j.version> <slf4j.version>1.7.36</slf4j.version>