IP白名单、网段白名单
IP白名单、网段白名单
以下是简化回最初需求、仅用一个列表存储且保留基础功能的版本,逻辑清晰、易于理解,适合轻量场景使用:
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;/*** IP 访问控制工具类(单列表存储 IP/网段,基础版)* 特点:逻辑简单,直接遍历判断,适合轻量场景*/
public class SimpleIpAccessControl {// 统一存储允许的 IP(直接存)和网段(CIDR 格式)private static final List<String> ALLOWED_ENTRIES = new ArrayList<>();static {// 初始化示例:单个 IP + 网段(CIDR 格式)ALLOWED_ENTRIES.add("192.168.1.100"); // 单个 IPALLOWED_ENTRIES.add("192.168.0.0/24"); // 网段(CIDR 格式)ALLOWED_ENTRIES.add("10.249.5.0/24"); // 网段ALLOWED_ENTRIES.add("172.16.0.0/16"); // 网段}/*** 检查 IP 是否被允许访问(基础版逻辑)* @param clientIp 客户端 IP 地址* @return 允许返回 true,否则 false*/public static boolean isAllowed(String clientIp) {for (String entry : ALLOWED_ENTRIES) {if (entry.contains("/")) {// 是网段(CIDR 格式),调用网段判断方法if (isIpInCidr(clientIp, entry)) {return true;}} else {// 是单个 IP,直接字符串匹配if (entry.equals(clientIp)) {return true;}}}return false;}/*** 判断 IP 是否在 CIDR 网段内(基础实现)* @param ip 客户端 IP* @param cidr 网段(CIDR 格式,如 192.168.0.0/24)* @return 在网段内返回 true*/private static boolean isIpInCidr(String ip, String cidr) {try {String[] cidrParts = cidr.split("/");if (cidrParts.length != 2) {return false; // 格式错误,视为不允许}InetAddress ipAddr = InetAddress.getByName(ip);InetAddress cidrAddr = InetAddress.getByName(cidrParts[0]);int prefixLength = Integer.parseInt(cidrParts[1]);// 将 IP 转换为字节数组byte[] ipBytes = ipAddr.getAddress();byte[] cidrBytes = cidrAddr.getAddress();// 逐位比较网络地址(前缀长度内的位必须一致)for (int i = 0; i < prefixLength; i++) {// 计算当前要比较的字节索引和位位置int byteIndex = i / 8;int bitPosition = 7 - (i % 8); // 字节高位在前(如 192.168.0.0 的第一个字节是 192,对应高位)// 提取 IP 和 CIDR 的对应位int ipBit = (ipBytes[byteIndex] >> bitPosition) & 1;int cidrBit = (cidrBytes[byteIndex] >> bitPosition) & 1;if (ipBit != cidrBit) {return false; // 某一位不匹配,不在网段内}}return true; // 所有前缀位匹配} catch (UnknownHostException e) {return false; // IP 解析失败,视为不允许}}// 测试示例public static void main(String[] args) {String[] testIps = {"192.168.1.100", // 单个 IP 允许"192.168.0.5", // 网段允许(192.168.0.0/24)"10.1.1.1", // 拒绝"10.249.5.100", // 网段允许(10.249.5.0/24)"172.16.5.5" // 网段允许(172.16.0.0/16)};for (String ip : testIps) {boolean allowed = isAllowed(ip);System.out.printf("IP: %-15s 允许访问: %s%n", ip, allowed);}}
}
核心逻辑说明
- 存储:用
ALLOWED_ENTRIES
一个列表存所有允许的条目,通过是否包含/
区分是单个 IP(直接字符串匹配)还是网段(需用isIpInCidr
校验)。 - 网段判断:将 IP 和网段的网络地址按二进制位逐位比较(只比较
prefixLength
长度内的位),一致则认为在网段内。 - 使用简单:调用
isAllowed(clientIp)
即可快速判断,适合对性能要求不极致、更看重代码简洁性的场景。
如果需要基础功能且不想引入复杂预处理,用这个版本就足够;若场景是高并发/多网段,再考虑之前的优化版即可。