解決request請求流只能讀取一次的問題

實際開發碰到的問題

springboot項目中,爲了防止sql注入,採用Filter攔截器對所有請求流中的json數據進行校驗,請求數據沒問題則繼續向下執行,在後邊的代碼中應用到請求參數值時,發現request中的json數據爲空;
除上邊描述的情況,嘗試過兩次從request中獲取json數據,第二次同樣是獲取不到的。

解決request請求流中的數據二次或多次使用問題

繼承HttpServletRequestWrapper,將請求體中的流copy一份,覆寫getInputStream()和getReader()方法供外部使用。每次調用覆寫後的getInputStream()方法都是從複製出來的二進制數組中進行獲取,這個二進制數組在對象存在期間一直存在,這樣就實現了流的重複讀取。

public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
    //保存流
    private byte[] requestBody = null;

    public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        requestBody = StreamUtils.copyToByteArray(request.getInputStream());
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {

        final ByteArrayInputStream bais = new ByteArrayInputStream(requestBody);

        return new ServletInputStream() {

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

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }
        };
    }

    @Override
    public BufferedReader getReader() throws IOException{
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }
}
@Component
@WebFilter
public class RequestSqlValidFilter implements Filter {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest)request);

        //請求參數合法,無sql注入
        if((sqlValid(request, response))){
            chain.doFilter(requestWrapper, response);//requestWrapper中保存着供二次使用的請求數據
        }else {
            logger.error("RequestSqlValidFilter sqlValid param error");
        }
    }

    @Override
    public void destroy() {

    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章