• 【Spring Boot】拦截器学习笔记


    一、普通拦截器

    1,新建类MyWebConfig实现WebMvcConfigurer,实现addInterceptors方法

    	@Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry
                    // 不拦截哪些请求
                    .excludePathPatterns("/login")
                    // 拦截哪些请求
                    .addPathPatterns("/location/**");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    经简单测试,默认是拦截所有,只有加了excludePathPatterns中的才不会拦截,该方法是链式的,可多次使用,参数也可以是多个,类似如下代码

     				// 不拦截哪些请求
                    .excludePathPatterns("/bb/**")
                    .excludePathPatterns("/aa/**","/scity/**");
    
    • 1
    • 2
    • 3

    2,新建配置类MyInterceptor实现HandlerInterceptor,同时MyWebConfig类里要加入@Bean注解和配置

    	// 添加配置
    	.addInterceptor(interceptor())
    	
        @Bean
        public MyInterceptor interceptor() {
            return  new MyInterceptor();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    MyInterceptor里处理拦截需求,实现preHandle方法

       @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    	 		String appId = request.getHeader("appId");
                boolean result = myComp.check(appId);
                if (result) {
                    log.info("通过拦截器");
                    return true;
                }
                setError(response,new ResponseData(1,"appId有误"));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    此处的check方法就是获取application.properties中的appId去和请求头中的appId比较,相同则通过,不同则报错
    3,新建一个Controller测试拦截器效果

    @Slf4j
    @RestController
    @RequestMapping("/aa")
    public class AAController {
    
     
        @PostMapping("/info")
        public String info(@RequestBody Object requestEntity) {
            String content = "aaa"+ JSON.toJSONString(requestEntity);
            log.info(content);
            return content;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述
    如果填了appId并且appId是正确的,那就可以返回正确的结果
    在这里插入图片描述

    二、带签名的拦截器

    1,思路:拦截器中除了常规的appId外,还加了一个sign参数,这个参数的生成规则是:使用url+body+key方式组合生成sha1签名,匹配前端接口header里的sign,可以做到防止请求被篡改。
    核心在于key,这个key是两方协商好的,这个key并不会在网络上传输,不可能被拦截到,除非人为透露。
    再严格一点可以加个时间戳

    2,修改preHandle方法,获取url、body,生成签名

    		// 获取接口地址
            String url = request.getRequestURL().toString();
            // 获取请求体 有待优化
            byte[] bodyBytes = StreamUtils.copyToByteArray(request.getInputStream());
            String body = new String(bodyBytes, request.getCharacterEncoding());
            // 签名前字符串,key=123456,可以是其他任意字符,和调用方约定好就行,该值无法被拦截到
            String sourceStr = url + body + "123456";
            // MD5签名
            String res = DigestUtils.md5DigestAsHex(sourceStr.getBytes(StandardCharsets.UTF_8));
            log.info(res);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3,比对sign

    		// 获取Header中sign进行比对
            String sign = request.getHeader("sign");
            if (res.equals(sign)) {
             	log.info("通过拦截器");
    		}else{
    		 	setError(response, "sign有误");
    		}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4,在postman调用测试接口,报错如下

    Resolved [org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public java.lang.String cn.xmliu.demo.controller.AAController.info(java.lang.Object)]

    问题原因主要就是request.getInputStram()在拦截器中已经取过了,到接口时数据已经丢失

    解决方法1:去掉@ResponseBody注解或设置为false
    解决方法2:增加body封装类,增加过滤器,启动类加bean,修改拦截器

    三,参考博文

    1,Required request body is missing
    2,springboot拦截器校验或鉴权导致Required request body is missing解决方法
    3,request.getinputstream只能读取一次

  • 相关阅读:
    【UV打印机】波形开发-开发流程(四)
    Python输出当前路径
    点云对齐/轨迹对齐方法及论文讲解
    Sass详解和应用
    GO语言学习笔记(与Java的比较学习)(三)
    anaconda安装配置
    cmake练习一
    JSP教学评估管理系统myeclipse开发mysql数据库bs框架java编程web网页结构
    多线程系列(一) -线程技术入门知识讲解
    【常驻进程内存优化】开机5分钟后常驻进程(Persistent)占用内存大小≤xxxMB,不达标
  • 原文地址:https://blog.csdn.net/diyangxia/article/details/132830559