前言
业务上有个需求,前端调用后端接口时传的是加密数据,所以后端无法正常接收数据。需要写一个过滤器,在过滤器那里拦截请求并解密数据。
问题复现
public Result create(@RequestBody String event) {
// do something
return Result.success();
}
由于前端传的是加密值,并不是Json数据,@RequestBody解析Json会抛出异常
解决方法
编写过滤器,拦截需要解密数据的请求。ServletRequest没有提供修改请求参数、请求体的方法,所以我们只能重写一个HttpServletRequestWrapper类,替换ServletRequest,拦截获取请求参数、请求体的方法,在方法内部进行解密。
启动类注解
@SpringBootApplication
// 加上@ServletComponentScan注解,自动扫描注册过滤器,否则@WebFilter注解不生效
@ServletComponentScan
public class RestApplication {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(RestApplication.class);
springApplication.run(args);
}
}
过滤器代码
@WebFilter(urlPatterns = "/accept/*",filterName = "KwaiMsgFilter")
public class KwaiMsgFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 用自己实现HttpServletRequestWrapper类,替换servletRequest
filterChain.doFilter(new KwaiMsgHttpServletRequestWrapper((HttpServletRequest) servletRequest), servletResponse);
}
}
KwaiMsgHttpServletRequestWrapper代码
public class KwaiMsgHttpServletRequestWrapper extends HttpServletRequestWrapper {
public KwaiMsgHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
/**
* 修改getInputStream方法
* @return
*/
@SneakyThrows
@Override
public ServletInputStream getInputStream() {
// 获取请求体数据
BufferedReader reader=super.getReader();
String str, wholeStr = "";
while((str = reader.readLine()) != null){
wholeStr += str;
}
// 解密
String msg=PlatformEventSecurityUtil.decode(wholeStr, "秘钥");
InputStream inputStream=new ByteArrayInputStream(msg.getBytes(StandardCharsets.UTF_8));
// 返回
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return inputStream.read();
}
};
}
}
总结
这样子Controller层就可以收到解密后的数据了,我这里只修改了getInputStream()方法,getParameter(String)等方法,可根据业务需求自己修改。