天天看點

友善快捷的HTTP比對

        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;
    }

}