springboot 學習之路 27(實現ip白名單功能)


背景:

  最近項目中遇到關於對部分請求設置ip白名單的功能需求,在這簡單梳理一下我的開發步驟與思路

實踐步驟:

  思路: 關於實現ip白名單的過濾我大致會想到三種實現方式:

  1. 對相關需要過濾的控制類進行單獨設置  -------------- 代碼臃腫,不利於維護
  2. 利用相關攔截器進行統一實現                --------------相對好實現   -----------我就以這種方法做介紹
  3. 前后端分離,讓前端控制ip請求             --------------你要是和前端關系好的話可以試試

 第一步:

   把相關的環境准備好,我這邊已經有現成的項目,我就在現成的項目進行演示,對其中涉及到保密的東西我會注釋掉,僅限參考

    

 

  大致的項目架構就是這樣,我主要在config包中進行相關攔截器的開發工作。

 

 

  先准備相關的攔截器:

  



/**
 * @author : HUHY    http://www.cnblogs.com/huhongy/
 * @Project_name:xxxxxxx
 * @date:2020/1/14 9:46
 * @email:hhy_0602@163.com
 * @description:{todo}
 */
@Slf4j
public class IPInterceptor implements HandlerInterceptor {

    @Autowired
    private ProjectTableDao projectTableDao;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("---------- 判斷相關ip");
        //先獲取相關需要驗證的ip列表
        //過濾ip,若用戶在白名單內,則放行
        String ipAddress=IPUtils.getRealIP(request);
        //所用需要驗證的ip,暫時批量驗證
        List<String> listIps = getListIps();
        if (listIps == null || listIps.size() == 0 || !listIps.contains(ipAddress) ){
            response.getWriter().print("請檢查ip白名單配置是否正確");
            return false;
        }
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }

    /**
     * 獲取符合要求的項目
     * @return
     */
    public List<String> getListIps(){
        /**
         * 保存最后結果
         */
        List<String> result  = new ArrayList<>();
        Map<String,Object> map = new HashMap<>();
        map.put("flag","1");
        map.put("enabled","1");
        List<ProjectTable> projectTables = projectTableDao.selectByMap(map);
        /**
         * @author: huhy   http://www.cnblogs.com/huhongy/
         */
        for (ProjectTable projectTable : projectTables) {
            String ips = projectTable.getIps();
            List<String> list = splitStr(ips);
            result.addAll(list);
        }
        return result;
    }

    /**
     * 吧ip拆分
     */
    public List<String> splitStr(String ips){
        List<String> temp = new ArrayList<>();
        String[] split = ips.split(",");
        List<String> list = Arrays.asList(split);
        /**
         * @author: huhy   http://www.cnblogs.com/huhongy/
         */
        for (String s : list) {
            temp.add(s);
        }
        return temp;
    }

}

  關於防止代理ip,獲取多ip的首位ip

 

public class IPUtils {
    /**
     * 獲取用戶真實IP地址,不使用request.getRemoteAddr()的原因是有可能用戶使用了代理軟件方式避免真實IP地址,
     * 可是,如果通過了多級反向代理的話,X-Forwarded-For的值並不止一個,而是一串IP值
     * @return ip
     */
    public static String getRealIP(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后會有多個ip值,第一個ip才是真實ip
            if( ip.indexOf(",")!=-1 ){
                ip = ip.split(",")[0];
            }
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
            System.out.println("Proxy-Client-IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
            System.out.println("WL-Proxy-Client-IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
            System.out.println("HTTP_CLIENT_IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            System.out.println("HTTP_X_FORWARDED_FOR ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
            System.out.println("X-Real-IP ip: " + ip);
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            System.out.println("getRemoteAddr ip: " + ip);
        }
        return ip;
    }
}

   最后一步,注冊攔截器即可:

  

@Configuration
public class InterceptorConfig  implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new ParamInterceptor()).addPathPatterns("/data/wuc/**");
        /**
         * 指定攔截的相關請求接口
         */
        //registry.addInterceptor(new ParamInterceptor()).addPathPatterns("/data/wuc/**");
    }

}

  

 


 

 到這,關於ip白名單的功能就完成了。有興趣的可以試一下


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM