diff --git a/fizz-bootstrap/pom.xml b/fizz-bootstrap/pom.xml index 1d22b7d..9e1fb67 100644 --- a/fizz-bootstrap/pom.xml +++ b/fizz-bootstrap/pom.xml @@ -18,7 +18,7 @@ Dragonfruit-SR3 Dysprosium-SR25 5.3.7.RELEASE - 4.1.90.Final + 4.1.91.Final 4.4.16 2.17.2 1.7.36 diff --git a/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/IpPlugin.java b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/IpPlugin.java new file mode 100644 index 0000000..1bb537d --- /dev/null +++ b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/IpPlugin.java @@ -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 filter(ServerWebExchange exchange, Map config) { + RouterConfig routerConfig = routerConfig(exchange, config); + List 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 pluginConfigItemList) { + Set fixedWhiteIpSet = Sets.newHashSet(); + Set fixedBlackIpSet = Sets.newHashSet(); + ApiConfig apiConfig = apiConfig(exchange); + Set 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 whiteIpSet = ConfigUtils.string2set(routerConfig.getWhiteIp()); + Set 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 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(ServerWebExchange exchange, Map 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)); + } + +} diff --git a/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/PluginConfig.java b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/PluginConfig.java new file mode 100644 index 0000000..c642c19 --- /dev/null +++ b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/PluginConfig.java @@ -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 configs = Lists.newArrayList(); + + @Data + public static class Item { + private String gwGroup; + private String whiteIp; + private String blackIp; + } +} diff --git a/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/RouterConfig.java b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/RouterConfig.java new file mode 100644 index 0000000..9db1741 --- /dev/null +++ b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/RouterConfig.java @@ -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"; + } +} diff --git a/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/ConfigUtils.java b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/ConfigUtils.java new file mode 100644 index 0000000..a29d03a --- /dev/null +++ b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/ConfigUtils.java @@ -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 string2set(String strVal, String charMatcherAnyOf) { + Set finalSet = Sets.newHashSet(); + if (StringUtils.isBlank(strVal)) { + return finalSet; + } + charMatcherAnyOf = StringUtils.isBlank(charMatcherAnyOf) ? DEFAULT_CHAR_MATCHER_ANY_OF : charMatcherAnyOf; + Set 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 string2set(String strVal) { + return string2set(strVal, DEFAULT_CHAR_MATCHER_ANY_OF); + } + +} diff --git a/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/IpMatchUtils.java b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/IpMatchUtils.java new file mode 100644 index 0000000..70124b6 --- /dev/null +++ b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/IpMatchUtils.java @@ -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 ipConfigList(String allowIp) { + // 拆分出白名单正则 + Set 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 ipConfigList(Set allowIpList) { + Set 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 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 complete(String arg) { + List 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 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 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); + } + +} \ No newline at end of file diff --git a/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/IpUtils.java b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/IpUtils.java new file mode 100644 index 0000000..64917c7 --- /dev/null +++ b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/IpUtils.java @@ -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 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> ipHeaders = Maps.newHashMap(); + Set>> headers = request.getHeaders().entrySet(); + for (Map.Entry> header : headers) { + String name = header.getKey(); + String lowerCaseName = name.toLowerCase(); + if (ipHeaderNames.contains(lowerCaseName)) { + List 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 clientIpList = ipHeaders.get(CLIENT_IP); // 取clientip与client-ip有区别 + ipAddress = fetchPublicIp(clientIpList); + // 若clientip为空或者是内网IP则取x-forwarded-for + if (StringUtils.isBlank(ipAddress)) { + List xForwardedIpList = ipHeaders.get(X_FORWARDED_FOR); + ipAddress = fetchPublicIp(xForwardedIpList); + } + // 若x-forwarded-for为空则取proxy-client-ip + if (StringUtils.isBlank(ipAddress)) { + List proxyClientIpList = ipHeaders.get(PROXY_CLIENT_IP); + ipAddress = fetchPublicIp(proxyClientIpList); + } + // 若proxy-client-ip为空则取wl-proxy-client-ip + if (StringUtils.isBlank(ipAddress)) { + List 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 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(); + } + +} diff --git a/pom.xml b/pom.xml index a6e3601..5309cc0 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ Dysprosium-SR25 5.3.7.RELEASE 2.2.7.RELEASE - 4.1.90.Final + 4.1.91.Final 4.4.16 2.17.2 1.7.36