SpringBoot 拦截器

作者: 我是曾经那个少年 | 来源:发表于2019-04-21 23:17 被阅读20次

    Interceptor可以在请求处理之前,请求处理之后进行干预,所以我们可以利用拦截器的特性进行一些例如日志打印,身份认证和授权,错误管理,接口限流等。

    1 使用拦截器

    1. 通过实现HandlerInterceptor接口自定义拦截器。
    2. 添加自定义拦截器到WebMvcConfigurerAdapter

    1.1 实现自定义拦截器

    我们打印出日志查看拦截器执行的顺序。

    public class UriInterceptor implements HandlerInterceptor{
        private Logger logger = LoggerFactory.getLogger(this.getClass());
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            logger.info("UriInterceptor preHandle controller 执行之前");
            return true;
        }
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                ModelAndView modelAndView) throws Exception {
            logger.info("UriInterceptor postHandle controller 执行之后,渲染视图之前");
        }
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
                throws Exception {
            logger.info("UriInterceptor afterCompletion  渲染视图之后");      
        }
    }
    

    1.2 添加自定义拦截器到WebMvcConfigurerAdapter

    @Configuration
    public class WebMvcConfigurer extends WebMvcConfigurerAdapter{
        @Bean
        public UriInterceptor uriInterceptor(){
            return new UriInterceptor();
        }
        /* 
         * 自定义拦截器添加到拦截器链中
         */
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            // addPathPatterns("/**");匹配所有请求
            // addPathPatterns("*.do");匹配.do结尾的请求
            registry.addInterceptor(uriInterceptor()).addPathPatterns("/**");
            super.addInterceptors(registry);
        }
    }
    

    1.3 请求测试

        @GetMapping("index")
        public String demo(){
            logger.info("DemoController index 正在执行!");
            return "查看拦截器的顺序";
        }
    

    查看执行日志记录

    请求先到拦截器的preHandle,再到控制器,再到postHandle ,再到afterCompletion 。

     [nio-8080-exec-1] c.l.s.web.interceptor.UriInterceptor     : UriInterceptor preHandle controller 执行之前
    [nio-8080-exec-1] c.l.s.web.controller.DemoController      : DemoController index 正在执行!
     [nio-8080-exec-1] c.l.s.web.interceptor.UriInterceptor     : UriInterceptor postHandle controller 执行之后,渲染视图之前
     [nio-8080-exec-1] c.l.s.web.interceptor.UriInterceptor     : UriInterceptor afterCompletion  渲染视图之后
    

    2 我们通过拦截器实现登录验证?

    1. 定义接口白名单,例如首页,登录页,问题页,部分活动页不需要登录授权就可以访问。
    2. 获取token。
    3. token校验。

    token的生成规则可以参考标准的JWT,或者自己内部定义即可。

    一般包括如下信息:用户标识信息,时间戳,签名算法,随机数

    例如 UID+时间戳(13位)+MD5+随机数

        // 定义接口白名单
        private static String[] INTERFACE_WHITE_LIST = {"login","index"};
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            logger.info("UriInterceptor preHandle controller 执行之前");
            String requestUri = request.getRequestURI();
            // 如果在接口白名单之前放行
            if (isWhilteList(requestUri)) {
                return true;
            }
            // 方案一  从请求头获取token
            String token = request.getHeader("token");
            // 方案二  从cookie获取token
            Cookie[] cookies = request.getCookies();
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals("token")) {
                    token = cookie.getValue();
                }
            }
            // token校验
            if (isMatch(token,request)) {
                // 判断token是否符合规则
                // token解析
                // 判断token是否正确
                // 判断token是否过期
                // 把用户信息放入request请求中
            }
            return false;
        }
    

    多个拦截器是怎么执行的?大家可以尝试一下,其实就是你添加到拦截器链中的先后顺序决定。

    源码下载 :Github

    传送门SpringBoot学习总结系列文章

    相关文章

      网友评论

        本文标题:SpringBoot 拦截器

        本文链接:https://www.haomeiwen.com/subject/srgsgqtx.html