springboot拦截器中修改text/plain请求体的数据
本帖最后由 wuqingvika 于 2023-4-21 11:42 编辑大佬们 有没有想法?
我的场景:
将请求来的密文数据请求拦截其中的text/plain报文体 取出对应的密文 变成明文 再丢给controller处理。我这里是不是哪里写错了。。。jsonStr就是转换好的明文Str。
这是Controller
报错【org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public java.lang.String brick.gcgs.controller.ywbdapController.handleTextPlain(java.lang.String)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:163)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:133)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:122)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:179)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:146)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
】
==================================已解决===========================================
后来改成了filter过滤器且@Component
public class MyFilter extends OncePerRequestFilter
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
String contentType = httpServletRequest.getHeader("Content-Type");
if (contentType != null && contentType.contains("text/plain")) { // 只处理text/plain请求数据
IDCTextPlainServletRequestWrapper myRequestWrapper = new IDCTextPlainServletRequestWrapper(httpServletRequest);
// TODO: 在这里对请求数据进行修改、验证等操作
String requestBodyStr = myRequestWrapper.getRequestBodyAsString();
//String requestBody = IOUtils.toString(httpServletRequest.getInputStream(), StandardCharsets.UTF_8);
//FIXME --用私钥解密text/plain文本数据---->拿到json明文数据
String jsonStr = null;
try {
jsonStr = RSAUtils.decrypt(requestBodyStr, “你自己的密钥”);
} catch (Exception e) {
e.printStackTrace();
}
//放行:对第4步的Json明文直接丢到接口中(这样接口中不需要验证这块繁琐的操作)
myRequestWrapper.setRequestBody(jsonStr.getBytes(StandardCharsets.UTF_8));
httpServletRequest = myRequestWrapper; // 使用自定义的HttpServletRequestWrapper对象来替换原始请求对象
}
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
再配置
@Bean
public FilterRegistrationBean myFilter ()
{
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new MyFilter());
//String[] urlPatterns = {"/api/*"};
registration.addUrlPatterns("/sync/**");
registration.setName("myFilter");
registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
return registration;
} 你把 @RequestBody改成@PathVariable 试试看 本帖最后由 vvvwxf 于 2023-4-20 17:59 编辑
你尝试 继承 OncePerRequestFilter 这个过滤器, 在doFilterInternal 方法中把你的请求体给转换成明文替换一下,然后放行试试呢 request 的body只能读取一次,可以用HttpServletRequestWrapper实现,wrapper里面要byte[] body; 记录一下body 另外 似乎在哪儿见到说 body 体 因为啥原因只能读一次,读过就再读不到了 要额外处理下。不确定是是不是 java里面的。 请求体只能读取一次,再植入进去有些困难(可以百度),我也是新手,我觉得可以写个AOP环绕通知,在before前做文章,轻喷 放到session的attr里面可不可行?用完再清理? 要 cache 一下 stream
懒人版
<!-- https://mvnrepository.com/artifact/io.github.zhengchalei/request-body-cache-spring-boot-starter -->
<dependency>
<groupId>io.github.zhengchalei</groupId>
<artifactId>request-body-cache-spring-boot-starter</artifactId>
<version>1.0.1</version>
</dependency>
加一个依赖 vvvwxf 发表于 2023-4-20 17:58
你尝试 继承 OncePerRequestFilter 这个过滤器, 在doFilterInternal 方法中把你的请求体给转换成明文替换一 ...
是的 后来就是改用Filter 继承那个说是一次过滤 hlking99 发表于 2023-4-21 02:13
放到session的attr里面可不可行?用完再清理?
这个也是一种方式 不过我想请求报文只接收text/plain不想从Request里取属性的方式
页:
[1]
2