IP段(CIDR格式)构建匹配库,传入IP查询是否命中

代码中有一些没用的自行去掉,我使用的CIDR格式,也可以通过IP的范围改造一下代码使用。

导入依赖

        
            com.github.seancfoley
            ipaddress
            5.3.3
        

IP匹配库工具类

package com.chun.utils;

import inet.ipaddr.AddressStringException;
import inet.ipaddr.IPAddress;
import inet.ipaddr.IPAddressSeqRange;
import inet.ipaddr.IPAddressString;
import org.apache.commons.net.util.SubnetUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

/**
 * @author chun
 * @date 2023/12/14 16:24
 */
public class IPMatcher {
    private static List<IPAddressSeqRange> ipRanges = new ArrayList<>();

    public static void readFile(File file) {
        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
            String line;
            while ((line = reader.readLine()) != null) {
                setIpRanges(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static boolean isIpRanges(String address) throws AddressStringException {
        for (IPAddressSeqRange ipRange : ipRanges) {
            boolean contains = ipRange.contains(new IPAddressString(address).toAddress());
            if (contains) {
                return true;
            }
        }
        return false;
    }

    public static void setIpRanges(String cidrAddress) {
        String startAddress = "";
        String endAddress = "";
        try {
            String[] split = cidrAddress.split("\\/");
            SubnetUtils utils = new SubnetUtils(cidrAddress);
            SubnetUtils.SubnetInfo subnetInfo = utils.getInfo();
            if (split[1].equals("32")) {
                startAddress = split[0];
                endAddress = split[0];
            } else {
                startAddress = subnetInfo.getLowAddress();
                endAddress = subnetInfo.getHighAddress();
            }

            System.out.println("IP CIDR=" + cidrAddress + ",IP范围:[" + startAddress + ", " + endAddress + "]");
        } catch (IllegalArgumentException e) {
            try {
                InetAddress networkAddress = InetAddress.getByName(cidrAddress.split("/")[0]);
                int subnetPrefixLength = Integer.parseInt(cidrAddress.split("/")[1]);

                BigInteger start = getStartAddress(networkAddress, subnetPrefixLength);
                BigInteger end = getEndAddress(start, subnetPrefixLength);

                startAddress = getAddressFromBigInteger(start);
                endAddress = getAddressFromBigInteger(end);

                System.out.println("IP CIDR=" + cidrAddress + ",IP范围:[" + startAddress + ", " + endAddress + "]");
            } catch (UnknownHostException ex) {
                ex.printStackTrace();
            }
        }

        IPAddress startIPAddress = new IPAddressString(startAddress).getAddress();
        IPAddress endIPAddress = new IPAddressString(endAddress).getAddress();
        ipRanges.add(startIPAddress.toSequentialRange(endIPAddress));
    }

    private static BigInteger getStartAddress(InetAddress networkAddress, int subnetPrefixLength) {
        ByteBuffer buffer = ByteBuffer.wrap(networkAddress.getAddress());
        BigInteger start = new BigInteger(1, buffer.array());

        return start.shiftRight(128 - subnetPrefixLength).shiftLeft(128 - subnetPrefixLength);
    }

    private static BigInteger getEndAddress(BigInteger start, int subnetPrefixLength) {
        BigInteger hostCount = BigInteger.ONE.shiftLeft(128 - subnetPrefixLength);
        return start.add(hostCount).subtract(BigInteger.ONE);
    }

    private static String getAddressFromBigInteger(BigInteger address) {
        byte[] bytes = address.toByteArray();
        InetAddress inetAddress;

        try {
            if (bytes.length == 16) {
                inetAddress = InetAddress.getByAddress(bytes);
            } else {
                byte[] paddedBytes = new byte[16];
                System.arraycopy(bytes, 0, paddedBytes, 16 - bytes.length, bytes.length);
                inetAddress = InetAddress.getByAddress(paddedBytes);
            }

            return inetAddress.getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

        return null;
    }
}

构建匹配库和读取配置文件

package com.chun.conf;

import com.chun.utils.IPMatcher;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

/**
 * @author chun
 * @date 2023/12/14 15:58
 */
@Slf4j
public class ReadConf {
    public static String url;
    public static String userName;
    public static String passWord;
    public static String userIpDir;
    public static String userIpFileMatch;

    public static void initPropertoesConf() throws IOException {
        Properties properties = new Properties();
        FileInputStream file = new FileInputStream(System.getProperty("user.dir") + "/test_pgsql/etc/conf.properties");
        properties.load(file);

        url = properties.getProperty("pgsql.url");
        userName = properties.getProperty("pgsql.userName");
        passWord = properties.getProperty("pgsql.passWord");
        userIpDir = properties.getProperty("user.ip.filepath");
        userIpFileMatch = properties.getProperty("user.ip.fileMatch");
    }

    public static void initUserIpConf() throws Exception {
        File[] files = getFiles(userIpDir, userIpFileMatch);
        if (files == null || files.length == 0) {
            log.error("The conf.properties user IP file path is incorrect! IP file number is 0");
            return;
        }
        for (File file : files) {
            IPMatcher.readFile(file);
        }
    }

    private static File[] getFiles(String dir, String fileNameMatch) {
        File fileDir = new File(dir);
        File[] files;
        if (fileDir.isDirectory()) {
            FileFilter fileFilter = new FileFilter() {
                @Override
                public boolean accept(File file) {
                    //判断文件名是否符合通配符规则
                    return file.getName().matches(fileNameMatch);
                }
            };
            files = fileDir.listFiles(fileFilter);
        } else {
            files = new File[1];
            files[0] = fileDir;
        }
        return files;
    }
}

conf.properties

pgsql.url=jdbc:postgresql://localhost:5432/School
pgsql.userName=postgres
pgsql.passWord=123456
user.ip.filepath=E:\\ProjectWorker\\TestJob\\test_pgsql\\etc\\
user.ip.fileMatch=ip.*

测试

传入文件列表:文件内容如下:

192.168.12.5/32
192.177.12.1/24
192.169.12.1/16
2001:0db8:85a3::/64
2001:0db8:85a4::/128
@Slf4j
public class Main {
    public static void main(String[] args) {
        ReadConf.initPropertoesConf();
        log.info("Start read conf.properties success!");
		ReadConf.initUserIpConf();
		log.info("Start read ip conf success!");

		System.out.println(IPMatcher.isIpRanges("192.168.1.1"));
		System.out.println(IPMatcher.isIpRanges("192.168.12.5"));
		System.out.println(IPMatcher.isIpRanges("192.177.12.1"));
		System.out.println(IPMatcher.isIpRanges("192.177.255.1"));
		System.out.println(IPMatcher.isIpRanges("192.169.255.254"));
		System.out.println(IPMatcher.isIpRanges("192.170.255.254"));
		System.out.println(IPMatcher.isIpRanges("2001:0db8:85a3::1234"));
		System.out.println(IPMatcher.isIpRanges("2001:0db8:85a4::ffff"));
		System.out.println(IPMatcher.isIpRanges("2001:0db8:85a4::"));
    }
}

结果

[INFO ] 2023-12-15 10:01:46.879 - Start read conf.properties success!
IP CIDR=192.168.12.5/32IP范围:[192.168.12.5, 192.168.12.5]
IP CIDR=192.177.12.1/24IP范围:[192.177.12.1, 192.177.12.254]
IP CIDR=192.169.12.1/16IP范围:[192.169.0.1, 192.169.255.254]
IP CIDR=2001:0db8:85a3::/64IP范围:[2001:db8:85a3:0:0:0:0:0, 2001:db8:85a3:0:ffff:ffff:ffff:ffff]
IP CIDR=2001:0db8:85a4::/128IP范围:[2001:db8:85a4:0:0:0:0:0, 2001:db8:85a4:0:0:0:0:0]
[INFO ] 2023-12-15 10:01:47.145 - Start read ip conf success!
false
true
true
false
true
false
true
false
true

你可能感兴趣的:(JAVA,IP段匹配库,CIDR,IPv4和IPv6)