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