【Spring Boot】拦截器学习笔记

一、普通拦截器

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

java 复制代码
	@Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry
                // 不拦截哪些请求
                .excludePathPatterns("/login")
                // 拦截哪些请求
                .addPathPatterns("/location/**");
    }

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

java 复制代码
 				// 不拦截哪些请求
                .excludePathPatterns("/bb/**")
                .excludePathPatterns("/aa/**","/scity/**");

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

java 复制代码
	// 添加配置
	.addInterceptor(interceptor())
	
    @Bean
    public MyInterceptor interceptor() {
        return  new MyInterceptor();
    }

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

java 复制代码
   @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有误"));
}

此处的check方法就是获取application.properties中的appId去和请求头中的appId比较,相同则通过,不同则报错

3,新建一个Controller测试拦截器效果

java 复制代码
@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;
    }

}

如果填了appId并且appId是正确的,那就可以返回正确的结果

二、带签名的拦截器

1,思路:拦截器中除了常规的appId外,还加了一个sign参数,这个参数的生成规则是:使用url+body+key方式组合生成sha1签名,匹配前端接口header里的sign,可以做到防止请求被篡改。

核心在于key,这个key是两方协商好的,这个key并不会在网络上传输,不可能被拦截到,除非人为透露。

再严格一点可以加个时间戳

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

java 复制代码
		// 获取接口地址
        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);

3,比对sign

java 复制代码
		// 获取Header中sign进行比对
        String sign = request.getHeader("sign");
        if (res.equals(sign)) {
         	log.info("通过拦截器");
		}else{
		 	setError(response, "sign有误");
		}

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只能读取一次

相关推荐
计算机程序设计开发31 分钟前
计算机毕业设计公交站点线路查询网站登录注册搜索站点线路车次/springboot/javaWEB/J2EE/MYSQL数据库/vue前后分离小程序
数据库·vue.js·spring boot·课程设计·计算机毕业设计
骆晨学长33 分钟前
基于SpringBoot的校园失物招领系统
java·spring boot
计算机编程-吉哥36 分钟前
计算机毕业设计 二手图书交易系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试
java·spring boot·毕业设计·毕业论文·计算机毕业设计选题·计算机毕业设计开题报告·二手图书交易系统
qq_353233538936 分钟前
【原创】java+springboot+mysql高校社团网系统设计与实现
java·spring boot·mysql
evanYang_1 小时前
Spring Boot配置文件敏感信息加密
spring boot·后端·oracle
huisheng_qaq1 小时前
【kafka-03】springboot整合kafka以及核心参数详解
spring boot·kafka·消息队列·topic·partition·kafka底层原理
晚枫20001 小时前
kafka发送事件的几种方式
spring boot·分布式·docker·容器·kafka·intellij-idea·linq
customer082 小时前
【开源免费】基于SpringBoot+Vue.JS网上超市系统(JAVA毕业设计)
java·vue.js·spring boot·后端·开源
ChinaRainbowSea2 小时前
十八,Spring Boot 整合 MyBatis-Plus 的详细配置
java·数据库·spring boot·spring·mybatis·web
我爱李星璇2 小时前
Spring Boot 常用注解
java·spring boot·后端