Java实现IP白名单校验工具类(单个IP或CIDR范围)

因响应等保评级需求,后端管理登录需加入双因素验证,即:
账号+密码+手机验证码或账号+密码+IP白名单过滤

因为是应付整改需求,怎么简单怎么来,ip白名单只需要在后端增加一个校验工具类即可。
说下思路,在数据库动态配置ip白名单列表,格式类似于阿里云安全组,可为单个固定ip(xxx.xxx.xxx.xxx),或CIDR范围格式(xxx.xxx.0.0/16)。管理端登陆时,对访问ip进行白名单校验,在白名单范围内即可顺利登录,否则拦截。

工具类代码如下:
import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.net.Inet4Address;
import java.util.regex.PatternSyntaxException;

public class IPWhitelistChecker {
    private List<String> whitelist;

    //本地调试时,localhost跳过判定
    private static Set<String> whiteSet = new HashSet<>(Arrays.asList(
            "0:0:0:0:0:0:0:1",
            "localhost",
            "127.0.0.1"
    ));

    public IPWhitelistChecker(List<String> whitelist) {
        this.whitelist = whitelist;
    }

    public boolean isIPInWhitelist(String ipToCheck) {
        if (whiteSet.contains(ipToCheck)){
            return true;
        }

        try {
            InetAddress ipAddress = InetAddress.getByName(ipToCheck);

            if (ipAddress instanceof Inet4Address) {
                for (String rule : whitelist) {
                    if (isValidIPRule(rule)) {
                        if (ipAddress.equals(InetAddress.getByName(rule))) {
                            return true;
                        }
                    } else if (isValidCIDRRule(rule)) {
                        if (isIPInCIDR(ipAddress, rule)) {
                            return true;
                        }
                    }
                }
            }
        } catch (UnknownHostException e) {
            // 处理无效的IP地址
        }

        return false;
    }

    private boolean isValidIPRule(String rule) {
        try {
            InetAddress.getByName(rule);
            return true;
        } catch (UnknownHostException e) {
            return false;
        }
    }

    private boolean isValidCIDRRule(String rule) {
        try {
            Pattern cidrPattern = Pattern.compile("^\\d+\\.\\d+\\.\\d+\\.\\d+\\/\\d+$");
            Matcher matcher = cidrPattern.matcher(rule);
            return matcher.matches();
        } catch (PatternSyntaxException e) {
            return false;
        }
    }

    private boolean isIPInCIDR(InetAddress ipAddress, String cidrRule) {
        try {
            String[] parts = cidrRule.split("/");
            String cidrAddress = parts[0];
            int prefixLength = Integer.parseInt(parts[1]);

            InetAddress cidrNetwork = InetAddress.getByName(cidrAddress);
            byte[] ipBytes = ipAddress.getAddress();
            byte[] networkBytes = cidrNetwork.getAddress();

            if (ipBytes.length != networkBytes.length) {
                return false;
            }

            for (int i = 0; i < prefixLength / 8; i++) {
                if (ipBytes[i] != networkBytes[i]) {
                    return false;
                }
            }

            int remainingBits = prefixLength % 8;
            if (remainingBits > 0) {
                int mask = 0xFF00 >> remainingBits;
                if ((ipBytes[prefixLength / 8] & mask) != (networkBytes[prefixLength / 8] & mask)) {
                    return false;
                }
            }

            return true;
        } catch (UnknownHostException e) {
            return false;
        }
    }

    public static void main(String[] args) {
        List<String> whitelist = new ArrayList<>();
        whitelist.add("111.130.33.179");
        whitelist.add("117.118.0.0/16");

        IPWhitelistChecker checker = new IPWhitelistChecker(whitelist);
        String ipToCheck = "111.130.33.179";

        if (checker.isIPInWhitelist(ipToCheck)) {
            System.out.println(ipToCheck + " 在白名单内");
        } else {
            System.out.println(ipToCheck + " 不在白名单内");
        }
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值