package com.yami.trading.common.util; import cn.hutool.core.util.StrUtil; import com.yami.trading.common.constants.Constants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.net.*; import java.util.*; import java.util.regex.Pattern; /** * 检测IP合法性工具类 * */ public class IpUtil { private static final Logger logger = LoggerFactory.getLogger(IpUtil.class); private static final String ANYHOST_VALUE = "0.0.0.0"; private static final String LOCALHOST_VALUE = "127.0.0.1"; private static volatile InetAddress LOCAL_ADDRESS = null; private static final int MIN_USER_PORT_NUMBER = 1024; private static final int MAX_USER_PORT_NUMBER = 65536; private static final long[][] intranet_ip_ranges = new long[][] { {ipToInt("10.0.0.0"), ipToInt("10.255.255.255")}, {ipToInt("172.16.0.0"), ipToInt("172.31.255.255")}, {ipToInt("192.168.0.0"), ipToInt("192.168.255.255")} }; public static String ipRegix = "((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"; public static Pattern ipPattern = Pattern.compile(ipRegix); private static String localIp = null; private static Pattern pattern; private static Pattern ptipv4; static { // ipv6 pattern = Pattern.compile("^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:)|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}(:[0-9A-Fa-f]{1,4}){1,2})|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){1,3})|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){1,4})|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){1,5})|([0-9A-Fa-f]{1,4}:(:[0-9A-Fa-f]{1,4}){1,6})|(:(:[0-9A-Fa-f]{1,4}){1,7})|(([0-9A-Fa-f]{1,4}:){6}(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){5}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){0,1}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){0,2}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|([0-9A-Fa-f]{1,4}:(:[0-9A-Fa-f]{1,4}){0,4}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(:(:[0-9A-Fa-f]{1,4}){0,5}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}))$"); // ipv4 ptipv4 = Pattern.compile("^(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$"); } /** * 正则表达式 判断字符是否为IP * */ public static boolean isCorrectIpRegular(String ipString) { if (StringUtils.isNullOrEmpty(ipString)) { return false; } boolean ipv6 = pattern.matcher(ipString).matches(); boolean ipv4 = ptipv4.matcher(ipString).matches(); if (!ipv6 && !ipv4) { System.out.println("IP不合法: " + ipString); return false; } return true; } public static boolean isIp(String in) { return in != null && ipPattern.matcher(in).matches(); } /** * 获取本机所有ip. * * @return map key为网卡名 value为对应ip */ public static Map getLocalIps() { try { Map result = new HashMap(); Enumeration netInterfaces = NetworkInterface.getNetworkInterfaces(); while (netInterfaces.hasMoreElements()) { NetworkInterface ni = netInterfaces.nextElement(); String name = ni.getName(); String ip = ""; Enumeration ips = ni.getInetAddresses(); while (ips.hasMoreElements()) { InetAddress address = ips.nextElement(); if (address instanceof Inet4Address) { ip = address.getHostAddress(); break; } } result.put(name, ip); } return result; } catch (SocketException e) { logger.error("getLocalIP error", e); return Collections.emptyMap(); } } /** * 获取服务器ip 判断规则 eth0 > eth1 > ... ethN > wlan > lo. */ public static String getLocalIp() { Map ips = getLocalIps(); List faceNames = new ArrayList(ips.keySet()); Collections.sort(faceNames); for (String name : faceNames) { if ("lo".equals(name)) { continue; } String ip = ips.get(name); if (StrUtil.isNotBlank(ip)) { return ip; } } return "127.0.0.1"; } /** * 只获取一次ip. */ public static String getSingleLocalIp() { if (localIp == null) { localIp = getLocalIp(); } return localIp; } /** * 随机返回可用端口. * * @return 端口号 */ public static int randomAvailablePort() { int port; do { port = (int) ((MAX_USER_PORT_NUMBER - MIN_USER_PORT_NUMBER) * Math.random()) + MIN_USER_PORT_NUMBER; } while (!availablePort(port)); return port; } /** * 检测该端口是否可用
端口必须大于 0 小于 {@value #MAX_USER_PORT_NUMBER}. * * @param port 端口号 * @return 是否可用 */ public static boolean availablePort(int port) { if (port < 0 || port > MAX_USER_PORT_NUMBER) { throw new IllegalArgumentException("Invalid port: " + port); } ServerSocket ss = null; DatagramSocket ds = null; try { ss = new ServerSocket(port); ss.setReuseAddress(true); ds = new DatagramSocket(port); ds.setReuseAddress(true); return true; } catch (IOException e) { // ignore } finally { if (ds != null) { ds.close(); } if (ss != null) { try { ss.close(); } catch (IOException e) { /* should not be thrown */ } } } return false; } /** * . */ public static String getRequestIp(HttpServletRequest request) { // just for test. if (request == null) { request = ApplicationUtil.getServletRequest(); if (request == null) { return null; } } String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("X-Real-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("X-Matrix-RemoteIP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("X-Original-Forwarded-For"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Fastly-Client-Ip"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("True-Client-Ip"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("X-Forwarded"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Forwarded-For"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Forwarded"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } if (ip != null && ip.length() != 0) { // 多次反向代理后会有多个ip值,第一个ip才是真实ip if (ip.indexOf(",") != -1) { ip = ip.split(",")[0]; } } //logger.info("获取日志打印【{}】", ip); return ip != null ? ip.trim() : "127.0.0.1"; } /** * 是否为内网ip A类 10.0.0.0-10.255.255.255 B类 172.16.0.0-172.31.255.255 C类 * 192.168.0.0-192.168.255.255 不包括回环ip. * * @param ip 需要判断的ip地址 * @return 是否是内网ip */ public static boolean isIntranetIP(String ip) { if (!isIp(ip)) { return false; } long ipNum = ipToInt(ip); for (long[] range : intranet_ip_ranges) { if (ipNum >= range[0] && ipNum <= range[1]) { return true; } } return false; } /** * Convert IP to Int. * * @param address ip地址 * @param isSegment true IP segment, false full IP. * @return 数字 */ public static int ipToInt(final String address, final boolean isSegment) { String customAddress = address; String[] ips = address.split(","); if (ips.length > 1) { customAddress = ips[0]; } final String[] addressBytes = customAddress.split("\\."); int length = addressBytes.length; if (length < 3) { return 0; } int ip = 0; try { for (int i = 0; i < 3; i++) { ip <<= 8; ip |= Integer.parseInt(addressBytes[i]); } ip <<= 8; if (isSegment || length == 3) { ip |= 0; } else { ip |= Integer.parseInt(addressBytes[3]); } } catch (Exception e) { throw new RuntimeException("Warn ipToInt address is wrong: address=" + address, e); } return ip; } /** * 将ip转化为数字,并且保持ip的大小顺序不变 如 ipToInt("10.75.0.1") > ipToInt("10.75.0.0") 如果ip不合法则返回 0. * * @param addr ip地址 * @return 数字 */ public static int ipToInt(final String addr) { return ipToInt(addr, false); } /** * ip转化为数字,并且保持ip的大小顺序不变 如果ip不合法则返回0. * ParseIP parses s as an IP address, returning the result. * The string s can be in IPv4 dotted decimal ("192.0.2.1"), IPv6 * ("2001:db8::68"), or IPv4-mapped IPv6 ("::ffff:192.0.2.1") form. * If s is not a valid textual representation of an IP address, * ParseIP returns nil. * @param addr ip地址 * @return 数字 */ public static long ipToLong(String addr) { if (addr == null) { return 0; } if (addr.contains(Constants.DOU_HAO)) { addr = addr.substring(0, addr.indexOf(Constants.DOU_HAO)); } //logger.info("ipToLong获取地址参数ip 【{}】", addr); if (addr.length() > 20) { return 0; } if (addr.length() < 4) { throw new RuntimeException("ip地址错误 wrong ipAddr format address=" + addr); } if (addr.contains(Constants.MAO_HAO)) { return 0; } final String[] addressBytes = addr.split("\\."); int length = addressBytes.length; if (length < 3) { return 0; } long ip = 0; try { for (int i = 0; i < 3; i++) { ip <<= 8; ip |= Integer.parseInt(addressBytes[i]); } ip <<= 8; if (length == 3) { ip |= 0; } else { ip |= Integer.parseInt(addressBytes[3]); } } catch (Exception e) { throw new RuntimeException("Warn ipToLong address is wrong: address=" + addr, e); } return ip; } /** * 将数字转化成ip. */ public static String intToIp(int ip) { return ((ip >> 24) & 0xFF) + "." + ((ip >> 16) & 0xFF) + "." + ((ip >> 8) & 0xFF) + "." + (ip & 0xFF); } /** * 将数字转化成ip. */ public static String longToIp(long ip) { return ((ip >> 24) & 0xFF) + "." + ((ip >> 16) & 0xFF) + "." + ((ip >> 8) & 0xFF) + "." + (ip & 0xFF); } private static InetAddress toValidAddress(InetAddress address) { if (address instanceof Inet6Address) { Inet6Address v6Address = (Inet6Address) address; if (isPreferIPV6Address()) { return normalizeV6Address(v6Address); } } if (isValidV4Address(address)) { return address; } return null; } private static boolean isPreferIPV6Address() { return Boolean.getBoolean("java.net.preferIPv6Addresses"); } /** * valid Inet4Address * * @param address * @return */ private static boolean isValidV4Address(InetAddress address) { if (address == null || address.isLoopbackAddress()) { return false; } String name = address.getHostAddress(); boolean result = (name != null && ptipv4.matcher(name).matches() && !ANYHOST_VALUE.equals(name) && !LOCALHOST_VALUE.equals(name)); return result; } /** * normalize the ipv6 Address, convert scope name to scope id. * e.g. * convert * fe80:0:0:0:894:aeec:f37d:23e1%en0 * to * fe80:0:0:0:894:aeec:f37d:23e1%5 *

* The %5 after ipv6 address is called scope id. * see java doc of {@link Inet6Address} for more details. * * @param address the input address * @return the normalized address, with scope id converted to int */ private static InetAddress normalizeV6Address(Inet6Address address) { String addr = address.getHostAddress(); int i = addr.lastIndexOf('%'); if (i > 0) { try { return InetAddress.getByName(addr.substring(0, i) + '%' + address.getScopeId()); } catch (UnknownHostException e) { // ignore logger.debug("Unknown IPV6 address: ", e); } } return address; } private static InetAddress getLocalAddress0() { InetAddress localAddress = null; try { localAddress = InetAddress.getLocalHost(); InetAddress addressItem = toValidAddress(localAddress); if (addressItem != null) { return addressItem; } } catch (Throwable e) { logger.error(e.getMessage(), e); } try { Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); if (null == interfaces) { return localAddress; } while (interfaces.hasMoreElements()) { try { NetworkInterface network = interfaces.nextElement(); if (network.isLoopback() || network.isVirtual() || !network.isUp()) { continue; } Enumeration addresses = network.getInetAddresses(); while (addresses.hasMoreElements()) { try { InetAddress addressItem = toValidAddress(addresses.nextElement()); if (addressItem != null) { try { if(addressItem.isReachable(100)){ return addressItem; } } catch (IOException e) { // ignore } } } catch (Throwable e) { logger.error(e.getMessage(), e); } } } catch (Throwable e) { logger.error(e.getMessage(), e); } } } catch (Throwable e) { logger.error(e.getMessage(), e); } return localAddress; } /** * Find first valid IP from local network card * * @return first valid local IP */ public static InetAddress getLocalAddress() { if (LOCAL_ADDRESS != null) { return LOCAL_ADDRESS; } InetAddress localAddress = getLocalAddress0(); LOCAL_ADDRESS = localAddress; return localAddress; } /** * get ip address * * @return String */ public static String getIp(){ return getLocalAddress().getHostAddress(); } /** * get ip:port * * @param port * @return String */ public static String getIpPort(int port){ String ip = getIp(); return getIpPort(ip, port); } public static String getIpPort(String ip, int port){ if (ip==null) { return null; } return ip.concat(":").concat(String.valueOf(port)); } public static Object[] parseIpPort(String address){ String[] array = address.split(":"); String host = array[0]; int port = Integer.parseInt(array[1]); return new Object[]{host, port}; } }