欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

方便快捷的HTTP匹配

程序员文章站 2022-05-19 10:09:43
...

        Http中常用到添加白名单,现在的业务是针对每一个ip配置不同的匹配规则来达到权限控制,这样,针对同一个ip在不能出现重复规则。


       因为用户输入的内容是复杂的,允许单个输入ip,也允许输入ip地址段,因此,需要提供一个工具类来匹配该ip是否已经存在。


      整体思想,讲用户输入的所有ip和ip段放入list集合中,在工具类调用时,将单个ip存放入list中,地址段转化为Map<Long,Long>类型,这样,在新添加的ip进行匹配时,只要匹配这两种类型即可:

/**
 * @author whp 17-12-4
 */
@Component
public class IPMatchUtils {
    private Map<Long,Long> purMap=new HashMap<>();
    private List<String> purList=new ArrayList<>();

    //记录已经配置过的ip
    public static String configuredIp;
    //记录非法ip
    public static String illegalIp;

    public IPMatchUtils(){};

    //该方法匹配两个list,res是要匹配的ip集合,pus是已经存在的ip集合
    public Boolean isUnique(List<String> res,List<String> pur){
        splitPurpose(pur);
        Boolean flag=true;
        for (String ip:res) {
            if(ip.contains("-")){
                String[] ips=ip.split("-");
                flag=(matchIp(ips[0]) && matchIp(ips[1]));
            }else{
                flag=matchIp(ip);
            }
            if(!flag){
                illegalIp=ip;
                return flag;
            }
        }
        return flag;
    }

    //匹配单个ip或者ip段
    public Boolean isMached(String ip,List<String> pur){
        splitPurpose(pur);
        Boolean flag=true;
        if(ip.contains("-")){
            String[] ips=ip.split("-");
            flag=(matchIp(ips[0]) && matchIp(ips[1]));
        }else{
            flag=matchIp(ip);
        }
        return (!flag);
    }

    private Boolean matchIp(String strIP){
        Boolean flag=true;
        if(purList.contains(strIP)){ //单个ip匹配只要ip集合中包含该ip即存在
            configuredIp=strIP;
            return false;
        }
        flag=matchIpAddressBlock(strIP);
        return flag;
    }

   //将ip转化为long类型数字
    private Long translateIpToLongNum(String strIp){
        Long ips = 0L;
        String[] numbers = strIp.split("\\.");
        //等价上面
        for (int i = 0; i < 4; ++i) {
            ips = ips << 8 | Integer.parseInt(numbers[i]);
        }
        return ips;
    }

    // 将ip分为单ip集合与ip段map
    private void splitPurpose(List<String> list){
        for (String ip:list) {
            if(ip.contains("-")){
                String[] ips=ip.split("-");
                Long start=translateIpToLongNum(ips[0]);
                Long end=translateIpToLongNum(ips[1]);
                if(start<end){
                    purMap.put(start,end);
                }else{
                    purMap.put(end,start);
                }
            }else{
                purList.add(ip);
            }
        }
    }

    private Boolean matchIpAddressBlock(String strIp){
        Iterator<Map.Entry<Long,Long>> it=purMap.entrySet().iterator();
        Long numIp=translateIpToLongNum(strIp);
        while (it.hasNext()){
            Map.Entry entry=it.next();
            if(numIp>=Long.parseLong(entry.getKey().toString()) && numIp<=Long.parseLong(entry.getValue().toString())){
                configuredIp=numberToIp(Long.parseLong(entry.getKey().toString()))+"-"+numberToIp(Long.parseLong(entry.getValue().toString()));
                return false;
            }
        }
        return true;
    }
    //将数字转化为ip
    private String numberToIp(long number){
        String ip = "";
        for (int i = 3; i >= 0; i--) {
            ip  = String.valueOf((number & 0xff))+ip;
            if(i != 0){
                ip = "."+ip;
            }
            number = number >> 8;
        }
        return ip;
    }

}