All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.hugh.util.ip.IpUtils Maven / Gradle / Ivy

There is a newer version: 2.7.14
Show newest version
package com.github.hugh.util.ip;

import com.github.hugh.util.regex.RegexUtils;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * IP工具类
 *
 * @author hugh
 * @since 1.0.4
 */
public class IpUtils {

    private IpUtils() {
    }

    /**
     * IP点号分隔符
     */
    private static final String REGEX_IP = "\\.";

    /**
     * 获取用户真实IP地址,不使用request.getRemoteAddr();的原因是有可能用户使用了代理软件方式避免真实IP地址
     * 

* 可是,如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP值,究竟哪个才是真正的用户端的真实IP呢? * 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。 *

* 如:X-Forwarded-For:192.168.1.110, 192.168.1.120, 192.168.1.130, 192.168.1.100 *

* 用户真实IP为: 192.168.1.110 * * @param request http请求 * @return String ip */ public static String get(HttpServletRequest request) { // X-Forwarded-For:Squid 服务代理 String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { // Proxy-Client-IP:apache 服务代理 ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { // WL-Proxy-Client-IP:weblogic 服务代理 ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { // HTTP_CLIENT_IP:有些代理服务器 ip = request.getHeader("HTTP_CLIENT_IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { // X-Real-IP:nginx服务代理 ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } // 有些网络通过多层代理,那么获取到的ip就会有多个,一般都是通过逗号(,)分割开来,并且第一个ip为客户端的真实IP if (ip != null && ip.length() != 0) { ip = ip.split(",")[0]; } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return ip; } /** * 随机生成国内IP地址 * * @return String ip */ public static String random() { // ip范围 int[][] range = {{607649792, 608174079}, // 36.56.0.0-36.63.255.255 {1038614528, 1039007743}, // 61.232.0.0-61.237.255.255 {1783627776, 1784676351}, // 106.80.0.0-106.95.255.255 {2035023872, 2035154943}, // 121.76.0.0-121.77.255.255 {2078801920, 2079064063}, // 123.232.0.0-123.235.255.255 {-1950089216, -1948778497}, // 139.196.0.0-139.215.255.255 {-1425539072, -1425014785}, // 171.8.0.0-171.15.255.255 {-1236271104, -1235419137}, // 182.80.0.0-182.92.255.255 {-770113536, -768606209}, // 210.25.0.0-210.47.255.255 {-569376768, -564133889}, // 222.16.0.0-222.95.255.255 }; Random random = new Random(); int index = random.nextInt(10); return num2ip(range[index][0] + new Random().nextInt(range[index][1] - range[index][0])); } /** * 将十进制转换成ip地址 * * @param ip IP * @return String */ private static String num2ip(int ip) { int[] b = new int[4]; b[0] = ((ip >> 24) & 0xff); b[1] = ((ip >> 16) & 0xff); b[2] = ((ip >> 8) & 0xff); b[3] = (ip & 0xff); return b[0] + "." + b[1] + "." + b[2] + "." + b[3]; } /** * 功能:判断一个IP是不是在一个网段下的 *

* 格式:isInRange("192.168.8.3", "192.168.9.10/22"); * * @param ip IP * @param cidr 网段地址 * @return boolean * @since 1.7.2 */ public static boolean isInRange(String ip, String cidr) { String[] ips = ip.split(REGEX_IP); int ipAddr = (Integer.parseInt(ips[0]) << 24) | (Integer.parseInt(ips[1]) << 16) | (Integer.parseInt(ips[2]) << 8) | Integer.parseInt(ips[3]); int type = Integer.parseInt(cidr.replaceAll(".*/", "")); int mask = 0xFFFFFFFF << (32 - type); String cidrIp = cidr.replaceAll("/.*", ""); String[] cidrIps = cidrIp.split(REGEX_IP); int cidrIpAddr = (Integer.parseInt(cidrIps[0]) << 24) | (Integer.parseInt(cidrIps[1]) << 16) | (Integer.parseInt(cidrIps[2]) << 8) | Integer.parseInt(cidrIps[3]); return (ipAddr & mask) == (cidrIpAddr & mask); } /** * 功能:根据位数返回IP总数 * 格式:parseIpMaskRange("192.192.192.1", "23") * * @param mask 掩码 * @return int * @since 1.7.2 */ public static int getIpCount(String mask) { return BigDecimal.valueOf(Math.pow(2, 32 - Integer.parseInt(mask))).setScale(0, BigDecimal.ROUND_DOWN).intValue();//IP总数,去小数点 } /** * 把long类型的Ip转为一般Ip类型:xx.xx.xx.xx * * @param ip IP * @return String * @since 1.7.2 */ public static String getIpFromLong(Long ip) { String s1 = String.valueOf((ip & 4278190080L) / 16777216L); String s2 = String.valueOf((ip & 16711680L) / 65536L); String s3 = String.valueOf((ip & 65280L) / 256L); String s4 = String.valueOf(ip & 255L); return s1 + "." + s2 + "." + s3 + "." + s4; } /** * 把xx.xx.xx.xx类型的转为long类型的 * * @param ip IP * @return long * @since 1.7.2 */ public static Long getIpFromString(String ip) { String ipTemp = ip; long ipLong = Long.parseLong(ipTemp.substring(0, ipTemp.indexOf('.'))); ipTemp = ipTemp.substring(ipTemp.indexOf('.') + 1); ipLong = ipLong * 256 + Long.parseLong(ipTemp.substring(0, ipTemp.indexOf('.'))); ipTemp = ipTemp.substring(ipTemp.indexOf(".") + 1); ipLong = ipLong * 256 + Long.parseLong(ipTemp.substring(0, ipTemp.indexOf('.'))); ipTemp = ipTemp.substring(ipTemp.indexOf('.') + 1); ipLong = ipLong * 256 + Long.parseLong(ipTemp); return ipLong; } /** * 根据掩码位获取掩码 * * @param maskBit 掩码位数,如"28"、"30" * @return String * @since 1.7.2 */ public static String getMaskByMaskBit(String maskBit) { return "".equals(maskBit) ? "error, maskBit is null !" : getNetmask(maskBit); } /** * 根据 ip/掩码位 计算IP段的起始IP 如 IP串 218.240.38.69/30 * * @param ip 给定的IP,如218.240.38.69 * @param maskBit 给定的掩码位,如30 * @return String 起始IP的字符串表示 * @since 1.7.2 */ public static String calcBeginIp(String ip, String maskBit) { return getIpFromLong(getBeginIpLong(ip, maskBit)); } /** * 根据 ip/掩码位 计算IP段的起始IP 如 IP串 218.240.38.69/30 * * @param ip 给定的IP,如218.240.38.69 * @param maskBit 给定的掩码位,如30 * @return long 起始IP的长整型表示 * @since 1.7.2 */ public static Long getBeginIpLong(String ip, String maskBit) { return getIpFromString(ip) & getIpFromString(getMaskByMaskBit(maskBit)); } /** * 根据 ip/掩码位 计算IP段的终止IP 如 IP串 218.240.38.69/30 * * @param ip 给定的IP,如218.240.38.69 * @param maskBit 给定的掩码位,如30 * @return String 终止IP的字符串表示 * @since 1.7.2 */ public static String calcEndIp(String ip, String maskBit) { return getIpFromLong(getEndIpLong(ip, maskBit)); } /** * 根据 ip/掩码位 计算IP段的终止IP 如 IP串 218.240.38.69/30 * * @param ip 给定的IP,如218.240.38.69 * @param maskBit 给定的掩码位,如30 * @return long 终止IP的长整型表示 * @since 1.7.2 */ public static Long getEndIpLong(String ip, String maskBit) { return getBeginIpLong(ip, maskBit) + ~getIpFromString(getMaskByMaskBit(maskBit)); } /** * 根据掩码位获取子网掩码 * * @param maskBit 掩码位 1-32 * @return String netmask * @since 1.7.2 */ public static String getNetmask(String maskBit) { switch (maskBit) { case "1": return "128.0.0.0"; case "2": return "192.0.0.0"; case "3": return "224.0.0.0"; case "4": return "240.0.0.0"; case "5": return "248.0.0.0"; case "6": return "252.0.0.0"; case "7": return "254.0.0.0"; case "8": return "255.0.0.0"; case "9": return "255.128.0.0"; case "10": return "255.192.0.0"; case "11": return "255.224.0.0"; case "12": return "255.240.0.0"; case "13": return "255.248.0.0"; case "14": return "255.252.0.0"; case "15": return "255.254.0.0"; case "16": return "255.255.0.0"; case "17": return "255.255.128.0"; case "18": return "255.255.192.0"; case "19": return "255.255.224.0"; case "20": return "255.255.240.0"; case "21": return "255.255.248.0"; case "22": return "255.255.252.0"; case "23": return "255.255.254.0"; case "24": return "255.255.255.0"; case "25": return "255.255.255.128"; case "26": return "255.255.255.192"; case "27": return "255.255.255.224"; case "28": return "255.255.255.240"; case "29": return "255.255.255.248"; case "30": return "255.255.255.252"; case "31": return "255.255.255.254"; case "32": return "255.255.255.255"; default: return "-1"; } } /** * 根据IP和位数(掩码)返回该IP网段的所有IP *

格式:parseIpMaskRange("192.192.192.1.", "23")

* * @param ip ip * @param mask 掩码 * @return List IP网段的所有IP * @since 1.7.2 */ public static List parseIpMaskRange(String ip, String mask) { List list = new ArrayList<>(); if ("32".equals(mask)) { list.add(ip); } else { String startIp = getBeginIpStr(ip, mask); String endIp = calcEndIp(ip, mask); if (!"31".equals(mask)) { String subStart = startIp.split(REGEX_IP)[0] + "." + startIp.split(REGEX_IP)[1] + "." + startIp.split(REGEX_IP)[2] + "."; String subEnd = endIp.split(REGEX_IP)[0] + "." + endIp.split(REGEX_IP)[1] + "." + endIp.split(REGEX_IP)[2] + "."; startIp = subStart + (Integer.parseInt(startIp.split(REGEX_IP)[3]) + 1); endIp = subEnd + (Integer.parseInt(endIp.split(REGEX_IP)[3]) - 1); } list = parseIpRange(startIp, endIp); } return list; } /** * 转换ip范围 * * @param startIp 起始IP地址 * @param endIp 结束IP地址 * @return List 起始与结束范围内的所有IP * @since 1.7.2 */ public static List parseIpRange(String startIp, String endIp) { List ips = new ArrayList<>(); String[] startIpArr = startIp.split(REGEX_IP); String[] endIpArr = endIp.split(REGEX_IP); int[] int_ipf = new int[4]; int[] int_ipt = new int[4]; for (int i = 0; i < 4; i++) { int_ipf[i] = Integer.parseInt(startIpArr[i]); int_ipt[i] = Integer.parseInt(endIpArr[i]); } for (int A = int_ipf[0]; A <= int_ipt[0]; A++) { for (int B = (A == int_ipf[0] ? int_ipf[1] : 0); B <= (A == int_ipt[0] ? int_ipt[1] : 255); B++) { for (int C = (B == int_ipf[1] ? int_ipf[2] : 0); C <= (B == int_ipt[1] ? int_ipt[2] : 255); C++) { for (int D = (C == int_ipf[2] ? int_ipf[3] : 0); D <= (C == int_ipt[2] ? int_ipt[3] : 255); D++) { ips.add(A + "." + B + "." + C + "." + D); } } } } return ips; } /** * 根据 ip/掩码位 计算IP段的起始IP 如 IP串 218.240.38.69/30 * * @param ip 给定的IP,如218.240.38.69 * @param maskBit 给定的掩码位,如30 * @return String 起始IP的字符串表示 * @since 1.7.2 */ public static String getBeginIpStr(String ip, String maskBit) { return getIpFromLong(getBeginIpLong(ip, maskBit)); } /** * 比较两个ip地址是否在同一个网段中 *
    *
  • * IP地址范围: 0.0.0.0~255.255.255.255,包括了mask地址。 IP地址划分 *
  • *
  • * A类地址:1.0.0.1~126.255.255.254 B类地址:128.0.0.1~191.255.255.254 *
  • *
  • * C类地址:192.168.0.0~192.168.255.255 D类地址:224.0.0.1~239.255.255.254 *
  • *
  • * E类地址:240.0.0.1~255.255.255.254 如何判断两个IP地址是否是同一个网段中: *
  • *
  • * 要判断两个IP地址是不是在同一个网段,就将它们的IP地址分别与子网掩码做与运算,得到的结果一网路号,如果网路号相同,就在同一子网,否则,不在同一子网。 *
  • *
  • * 例:假定选择了子网掩码255.255.254.0,现在分别将上述两个IP地址分别与掩码做与运算,如下图所示: *
  • *
  • * 211.95.165.24 11010011 01011111 10100101 00011000 *
  • *
  • * 255.255.254.0 11111111 11111111 111111110 00000000 *
  • *
  • * 与的结果是: * 11010011 01011111 10100100 00000000 *
  • *
  • * 211.95.164.78 11010011 01011111 10100100 01001110 *
  • *
  • * 255.255.254.0 11111111 11111111 111111110 00000000 *
  • *
  • * 与的结果是: * 11010011 01011111 10100100 00000000 *
  • *
  • * 可以看出,得到的结果(这个结果就是网路地址)都是一样的,因此可以判断这两个IP地址在同一个子网。 * 如果没有进行子网划分,A类网路的子网掩码为255.0.0.0,B类网路的子网掩码为255.255.0.0,C类网路的子网掩码为255.255.255.0,预设情况子网掩码为255.255.255.0 *
  • *
* * @param ip1 第一个IP地址 * @param ip2 第二个IP地址 * @param mask 子网掩码 * @return boolean * @since 2.0.3 */ public static boolean isSameNetworkSegment(String ip1, String ip2, String mask) { if (RegexUtils.isNotIp(ip1)) { return false; } if (RegexUtils.isNotIp(ip2)) { return false; } int maskInt = getIpV4Value(mask); int ipValue1 = getIpV4Value(ip1); int ipValue2 = getIpV4Value(ip2); return (maskInt & ipValue1) == (maskInt & ipValue2); } /** * 两个IP不在同一网段内 * * @param ip1 第一个IP地址 * @param ip2 第二个IP地址 * @param mask 子网掩码 * @return boolean * @see #isSameNetworkSegment(String, String, String) * @since 2.0.5 */ public static boolean isNotSameNetworkSegment(String ip1, String ip2, String mask) { return !isSameNetworkSegment(ip1, ip2, mask); } /** * 计算ipv4 地址int值 * * @param ipOrMask ip或子网掩码 * @return int * @since 2.0.3 */ public static int getIpV4Value(String ipOrMask) { byte[] addr = getIpV4Bytes(ipOrMask); int address1 = addr[3] & 0xFF; address1 |= ((addr[2] << 8) & 0xFF00); address1 |= ((addr[1] << 16) & 0xFF0000); address1 |= ((addr[0] << 24) & 0xFF000000); return address1; } /** * 获取ipV4的位元组 * * @param ipOrMask ip或子网掩码 * @return byte[] * @since 2.0.3 */ public static byte[] getIpV4Bytes(String ipOrMask) { try { String[] addrs = ipOrMask.split("\\."); int length = addrs.length; byte[] addr = new byte[length]; for (int index = 0; index < length; index++) { addr[index] = (byte) (Integer.parseInt(addrs[index]) & 0xff); } return addr; } catch (Exception e) { } return new byte[4]; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy