主页 > 人工智能  > 

使用HttpServletRequestWrapper解决web项目request数据流无法重复读取的问题


在做web项目开发时,我们有时候需要做一些前置的拦截判断处理,比如非法参数校验,防攻击拦截,统一日志处理等,而请求参数如果是form表单提交还好处理;对于json这种输入流的数据就会有问题,统一处理如果读取了数据流就会将流进行关闭,这就会导致接下来的业务处理无法读取数据流。为了解决这个问题,需要将request中的输入流包装为可以重复读取的数据流,具体的操作如下: 自定义一个类继承HttpServletRequestWrapper,并实现它里面的相关方法:

import cn.hutool.core.io.IoUtil; import jakarta.servlet.ReadListener; import jakarta.servlet.ServletInputStream; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequestWrapper; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; /** * @Author xingo * @Date 2024/1/26 */ public class RepeatableReadRequestWrapper extends HttpServletRequestWrapper { private final byte[] body; public RepeatableReadRequestWrapper(HttpServletRequest request) throws IOException { super(request); request.setCharacterEncoding("UTF-8"); body = IoUtil.readBytes(request.getInputStream()); } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(getInputStream())); } @Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream bis = new ByteArrayInputStream(body); return new ServletInputStream() { @Override public int read() throws IOException { return bis.read(); } @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } }; } }

封装成这个类就是为了解决需要重复读取输入流的地方就使用这个包装类替换原有的request对象。再定义一个过滤器用于模拟统一处理请求参数,下面就简单模拟在参数中取用户名的过滤器:

import com.fasterxml.jackson.databind.JsonNode; import jakarta.servlet.*; import jakarta.servlet.annotation.WebFilter; import jakarta.servlet.http.HttpServletRequest; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import java.io.IOException; import java.util.Objects; /** * @Author xingo * @Date 2024/1/26 */ @Order(value = Ordered.LOWEST_PRECEDENCE - 1) @Component @WebFilter(filterName = "paramsFilter", urlPatterns = "/*") public class CheckParamsFilter implements Filter { private ServletContext context; static final String checkKey = "userName"; @Override public void init(FilterConfig filterConfig) throws ServletException { Filter.super.init(filterConfig); context = filterConfig.getServletContext(); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; ServletRequest requestWrapper = null; String userName = null; String contentType = request.getContentType(); if(contentType != null && contentType.contains(MediaType.APPLICATION_JSON_VALUE)) { try { // 对于需要读取输入流的先对request进行包装处理,这样后续再次需要读取数据流时就可以正常读到 requestWrapper = new RepeatableReadRequestWrapper(request); JsonNode jsonNode = JacksonUtils.getObjectMapper().readTree(requestWrapper.getInputStream()); if(jsonNode.get(checkKey) != null) { userName = jsonNode.get(checkKey).asText(); } } catch (Exception e) { e.printStackTrace(); } } else { try { if(request.getParameter(checkKey) != null) { userName = request.getParameter(checkKey); } } catch (Exception e) { e.printStackTrace(); } } if(userName != null) { // 这里判断用户名检查成功就放行、否则就返回失败信息,在放行处理时需要判断是否需要传递包装request if(this.check(userName)) { chain.doFilter(Objects.requireNonNullElse(requestWrapper, servletRequest), servletResponse); } servletResponse.setContentType("application/json; charset=utf-8"); servletResponse.getWriter().print(JacksonUtils.toJSONString(ApiResult.fail(400, "信息验证失败"))); return; } chain.doFilter(Objects.requireNonNullElse(requestWrapper, servletRequest), servletResponse); } @Override public void destroy() { Filter.super.destroy(); } private boolean check(String userName) { return "admin".equals(userName); } }
标签:

使用HttpServletRequestWrapper解决web项目request数据流无法重复读取的问题由讯客互联人工智能栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“使用HttpServletRequestWrapper解决web项目request数据流无法重复读取的问题