wuqingvika 发表于 2023-4-20 16:45

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;
    }

chsnl 发表于 2023-4-20 17:13

你把 @RequestBody改成@PathVariable 试试看

vvvwxf 发表于 2023-4-20 17:58

本帖最后由 vvvwxf 于 2023-4-20 17:59 编辑

你尝试 继承 OncePerRequestFilter 这个过滤器, 在doFilterInternal 方法中把你的请求体给转换成明文替换一下,然后放行试试呢

namedlxd 发表于 2023-4-20 18:07

request 的body只能读取一次,可以用HttpServletRequestWrapper实现,wrapper里面要byte[] body; 记录一下body

pjy612 发表于 2023-4-20 18:08

另外 似乎在哪儿见到说 body 体 因为啥原因只能读一次,读过就再读不到了 要额外处理下。不确定是是不是 java里面的。

寒流溯雪灬 发表于 2023-4-20 22:46

请求体只能读取一次,再植入进去有些困难(可以百度),我也是新手,我觉得可以写个AOP环绕通知,在before前做文章,轻喷

hlking99 发表于 2023-4-21 02:13

放到session的attr里面可不可行?用完再清理?

萋小磊 发表于 2023-4-21 03:38

要 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>

加一个依赖

wuqingvika 发表于 2023-4-21 11:43

vvvwxf 发表于 2023-4-20 17:58
你尝试 继承 OncePerRequestFilter 这个过滤器, 在doFilterInternal 方法中把你的请求体给转换成明文替换一 ...

是的 后来就是改用Filter 继承那个说是一次过滤

wuqingvika 发表于 2023-4-21 11:43

hlking99 发表于 2023-4-21 02:13
放到session的attr里面可不可行?用完再清理?

这个也是一种方式 不过我想请求报文只接收text/plain不想从Request里取属性的方式
页: [1] 2
查看完整版本: springboot拦截器中修改text/plain请求体的数据