• 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白名单的功能就完成了。有兴趣的可以试一下

  • 相关阅读:
    记我安装Caffe的血泪史(1)
    UWP连接mysql 实现数据远程备份
    数据库性能测试
    性能瓶颈分析定位
    系统安全性测试
    WEB安全性测试点
    jmeter测试报告分析
    Linux常用命令大全
    软件测试入门到飞升上仙之客户端
    软件测试入门到飞升上仙之web 端测试
  • 原文地址:https://www.cnblogs.com/huhongy/p/12192310.html
Copyright © 2020-2023  润新知