zoukankan      html  css  js  c++  java
  • spring boot 学习(十二)拦截器实现IP黑名单

    拦截器实现IP黑名单

    前言

    最近一直在搞 Hexo+GithubPage 搭建个人博客,所以没怎么进行 SpringBoot 的学习。所以今天就将上次的”?秒防刷新”进行了一番修改。上次是采用注解加拦截器(@Aspect)来实现功能的。但是,如果需求是一个全局的拦截器对于大部分URL都进行拦截的话,自己一个个加显然是不可能的。而且上次的拦截器对于Controller的参数有所要求,在实际他人引用总是显得不方便。所以,这次使用了继承HandlerInterceptor来实现拦截器。

    功能需求

    对于项目中某类URL进行拦截,若用户在短时间内大量访问该链接,则将用户IP列入黑名单,禁止用户访问网页。(同时,可以使用@Async来创建定时任务帮用户解禁。)

    准备

    ?秒防刷新的业务逻辑

    博客地址 : http://blog.csdn.net/u011244202/article/details/54783337
    项目参考地址 : https://github.com/FunriLy/springboot-study/tree/master/%E6%A1%88%E4%BE%8B5

    SpringBoot+Druid+MyBatis

    博客地址 : http://blog.csdn.net/u011244202/article/details/54709060
    项目参考地址 : https://github.com/FunriLy/springboot-study/tree/master/%E6%A1%88%E4%BE%8B1

    知识记录

    Spring 的拦截器 HandlerInterceptor 的功能跟过滤器类似,但是提供更精细的的控制能力:在request被响应之前、request被响应之后、视图渲染之前以及request全部结束之后。我们不能通过拦截器修改request内容,但是可以通过抛出异常(或者返回false)来暂停request的执行。
    配置拦截器也很简单,Spring 为此提供了基础类WebMvcConfigurerAdapter ,我们只需要重写addInterceptors 方法添加注册拦截器。

    实现自定义拦截器只需要3步:
    1、创建我们自己的拦截器类并实现 HandlerInterceptor 接口。
    2、创建一个 Java 类继承 WebMvcConfigurerAdapter,并重写 addInterceptors 方法。
    3、实例化我们自定义的拦截器,然后将对像手动添加到拦截器链中(在addInterceptors方法中添加)。

    正式开工

    IP工具类

    由于不清楚用户代理,最好能使用一个工具类来来获取用户真实IP。这个Google就能找到,我就不贴代码了。

    数据库

    我使用的是MySQL数据库,持久层框架为MyBatis。具体可参考”准备”步骤。
    我在”myboot”数据库中创建一张表”blaclist”,属性如下:

    字段名解释
    id 记录的id
    ip 用户真实IP
    iptime IP被锁时间

    实体类

    public class BlackList {
    
        private int id;
        private String ip;
        private Date iptime; // 日期类型,格式:yyyy-MM-dd HH:mm:ss
        //构造器
        public BlackList() {
        }
    
        public BlackList(String ip, Date iptime) {
            this.ip = ip;
            this.iptime = iptime;
        }
        // get && set 方法
    }
    

    Dao层

    注意XML配置与对应实体配置(省略)。

    @Mapper
    public interface BlackListDao {
        // 根据IP来查找记录
        List<BlackList> findByIp(String ip);
        // 添加记录
        int addBlackList(@Param("blackList") BlackList blackList);
    }
    

     实现 HandlerInterceptor 接口

    public class URLInterceptor implements HandlerInterceptor {
    
        @Autowired
        BlackListDao blackListDao;
    
        private Map<String, Integer> redisTemplate = new HashMap<String, Integer>();
        private static final Logger logger = LoggerFactory.getLogger(URLInterceptor.class);
    
        //在请求处理之前进行调用(Controller方法调用之前)
        @Override
        public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
            return true;
        }
    
        //请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
        @Override
        public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
            String ip = IPAddressUtil.getClientIpAddress(httpServletRequest);
            List<BlackList> blackLists = blackListDao.findByIp(ip);
            if (blackLists == null || blackLists.size() == 0){
                urlHandle(httpServletRequest, 5000, 10);
            } else {
                //强制控制跳转
                modelAndView.setViewName("/errorpage/error.html");
            }
        }
    
        //在整个请求结束之后被调用
        @Override
        public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    
        }
    
        public void urlHandle(HttpServletRequest request, long limitTime,int limitCount) throws RequestLimitException {
                /**
                 * 省略业务逻辑部分,参考"准备"步骤
                 */
                if (count > limitCount){ //符合锁定条件
                    Calendar calendar = Calendar.getInstance();
                    Date iptime=calendar.getTime();
                    BlackList blackList = new BlackList(ip, iptime);
                    blackListDao.addBlackList(blackList);
                    throw new RequestLimitException();
                }
        }
    }
    

    WebMvcConfigurerAdapter类

    配置 spring mvc的拦截器 WebMvcConfigurerAdapter。

    @Configuration
    public class MyWebAppConfigurer extends WebMvcConfigurerAdapter {
    
        @Bean   //把我们的拦截器注入为bean
        public HandlerInterceptor getMyInterceptor(){
            return new URLInterceptor();
        }
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            // 多个拦截器组成一个拦截器链
            // addPathPatterns 用于添加拦截规则, 这里假设拦截 /url 后面的全部链接
            // excludePathPatterns 用户排除拦截
            registry.addInterceptor(getMyInterceptor()).addPathPatterns("/url/**");
            super.addInterceptors(registry);
        }
    }
    

     Controller类

        @RequestMapping("/url/test")
        @ResponseBody
        public String URLtest() {
            return "success";
        }
    
  • 相关阅读:
    算法----递归
    函数调用栈、任务队列、事件轮询、宏任务、微任务
    苹果浏览器和ios中,时间字符串转换问题
    npm 命令行基本操作
    一些积累(做阿里笔试题)……
    CSS reset
    一些正则表达式的实例,供参考使用
    不同浏览器获取不同高与宽的方法
    盒子模型
    CSS中的字体样式和文本样式
  • 原文地址:https://www.cnblogs.com/MaxElephant/p/8108570.html
Copyright © 2011-2022 走看看