继承HttpServletRequestWrapper实现流重复读、参数过滤等场景

2022-07-31,,,,

背景

   项目基于springboot开发,RestFull接口向外暴露的API需要进行签名验证,即在进入真正controller方法前,需要先验证接口请求的有效性,所以需要对提交的POST流进行JSON读,并将相关参数进行验签。如果在Filter中使用request.getInputStream()来获取流来得到body中的信息,可以达到预期效果,但是流的获取只能获取一次,之后再获取就获取不到了,导致controller无法拿到参数而报错。参考相关资料发现实现一个类继承HttpServletRequestWrapper,重写其中的getInputStream方法,让其可以重复获取我们想要的流。

自定义RequestWrapper类

package com.argrace.platform.interceptor;

import com.argrace.platform.exception.VeecloudBizException;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RequestWrapper extends HttpServletRequestWrapper {
   private static final Logger log = LoggerFactory.getLogger(RequestWrapper.class);
   private String mBody;

   public RequestWrapper(HttpServletRequest request) {
      super(request);
      this.mBody = this.getBody(request);
   }

   public static String convertStreamToString(InputStream is) {
      BufferedReader reader = new BufferedReader(new InputStreamReader(is));
      StringBuilder sb = new StringBuilder();

      try {
         String line;
         try {
            while((line = reader.readLine()) != null) {
               sb.append(line + "\n");
            }
         } catch (IOException var13) {
            log.error("IOException", var13);
         }
      } finally {
         try {
            is.close();
         } catch (IOException var12) {
            log.error("IOException", var12);
         }

      }

      return sb.toString();
   }

   private String getBody(HttpServletRequest request) {
      try {
         return convertStreamToString(request.getInputStream());
      } catch (IOException var3) {
         log.debug(var3.getMessage());
         throw new VeecloudBizException(var3);
      }
   }

   public String getBody() {
      return this.mBody;
   }

   public BufferedReader getReader() throws IOException {
      return new BufferedReader(new InputStreamReader(this.getInputStream()));
   }

   public ServletInputStream getInputStream() throws IOException {
      final ByteArrayInputStream bais = new ByteArrayInputStream(this.mBody.getBytes(Charset.defaultCharset()));
      return new ServletInputStream() {
         public boolean isFinished() {
            return false;
         }

         public boolean isReady() {
            return false;
         }

         public void setReadListener(ReadListener readListener) {
         }

         public int read() throws IOException {
            return bais.read();
         }
      };
   }
}

实用案例

代码块:

public void test(HttpServletRequest request, HttpServletResponse response) throws Exception {
      String param;
      if (this.isJson(request)) {
         param = (new RequestWrapper(request)).getBody();
         log.info("[test] 获取到application/json请求参数 : {}", param);
      } else {
         SortedMap<String, String> map = this.getAllParams(request);
         param = JSON.toJSONString(map);
         log.info("[test] 获取到application/x-www-form-urlencoded请求参数 : {}", param);
      }
}
private boolean isJson(HttpServletRequest request) {
      if (request.getContentType() == null) {
         return false;
      } else {
         return request.getContentType().equals("application/json") || request.getContentType().equals("application/json;charset=UTF-8");
      }
   }

本文地址:https://blog.csdn.net/keyingbo2008/article/details/107684691

《继承HttpServletRequestWrapper实现流重复读、参数过滤等场景.doc》

下载本文的Word格式文档,以方便收藏与打印。