Springboot使用过滤器中关于获取multipart/form-data表单数据问题记录
最近项目组因为token检验拿不到content-type=multipart/form-data表单数据产生疑惑,后翻查了网上的资料总结。前端content-type=application/x-www-form-urlencoded传入后端时,我们可以通过getParameter的方法获取到参数。HttpServletRequest request = (HttpServletRequest)
最近项目组因为token检验拿不到content-type=multipart/form-data表单数据产生疑惑,后翻查了网上的资料总结。
前端content-type=application/x-www-form-urlencoded传入后端时,我们可以通过getParameter的方法获取到参数。
HttpServletRequest request = (HttpServletRequest)servletRequest;
String value = request.getParameter("key");
备注:content-type=application/x-www-form-urlencoded通过加密参数拼接在url上,后端会解析出来并放入一个map中,供重复使用。
除了content-type=application/x-www-form-urlencoded这种情况,项目还会涉及上传文件,这里就会用到另外一种content-type=multipart/form-data,这时我们通过request.getParameter("key")来获取参数会返回一个null,因为参数不再是通过加密传url进来,而是通过流的形式传入。
此时我们就需要用到MultipartResolver接口来帮助我们获取得到content-type=multipart/form-data提交上来的参数。
MultipartResolver有两个实现类一个是CommonsMultipartResolver类,另外一个是StandardServletMultipartResolver类,这里示范一下CommonsMultipartResolver的解析方法:
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
MultipartHttpServletRequest multReq = resolver.resolveMultiparrt(request);
String value = multReq.getParametter("key");
问题:通过上面的方法我们成功获取得到前端传给我们的参数,但是另外一个问题出现了,就是我们的流只能够读取一次,读取完之后的request就等于一个空掉的杯子,导致后续的方法都拿不到参数。这是因为我们漏了一个步骤:
request = multReq;
filterChain.doFilter(request, servletResponse);
备注:我们需要把解析完之后的request重新赋值,这样我们就不会丢失掉数据。
最后分享一下我这边项目的一个情况就是重新解析后的request虽然能获取params,但是因为流被解析了导致这边底层解析流获取file的方法失效,这边是通过学习码友们把inputstream流复制出来重复使用,达成我想要的效果~
MyHttpServletRequestWrappet类:
public class MyHttpServletRequestWrappet extends HttpServletRequestWrapper{
private final byte[] body;
public MyHttpServletRequestWrappet(HttpServletRequest request) throws IOException{
super(request);
body = StreamUtils.copyToByteArray(request.getInputStream());
}
@Override
public BufferedReader getReader() throws IOException{
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream(){
@Override
public boolean isFinished(){return false;}
@Override
public boolean isReady(){return false;}
@Override
public void setReadListener(ReadListener readListener){}
@Override
public int read() throws IOException {
return bais.read();
}
};
}
}
Filter类:
@WebFilter(filterName = "tokenFilter", urlPatterns = "/*")
public class TokebFilter implements Filter{
private static final String FORM_DATA = "multipart/form-data";
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
//跳过白名单检验方法
String requestUri = getRequestUri(request);
if("/signin".equalsIgnoreCase(requestUri)
|| "/signoff".equalsIgnoreCase(requestUri)){
filterChain.doFilter(servletRequest, servletResponse);
return;
} else {
//token设置在头部则不需要去取参数
String token = request.getHeader("token");
if(StringUtils.isEmpty(token)){
token = request.getParameter("token");
}
if(request.getContentType() != null && request.getContentType().contains(FORM_DATA)){
MyHttpServletRequestWrapper requestWrapper = new MyHttpServletRequestWrapper(request);
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
MultipartHttpServletRequest multReq = resolver.resolverMultipart(requestWrapper);
token = multReq.getParameter("token");
request = requeatWrapper;
}
HttpSession session = request.getSession(false);
Object sessionToken = session.getAttribute("token");
if(!sessionToken.equals(token)
|| StringUtils.isBlank(token)){
servletResponse.setCharacterEncoding("UTF-8");
servletResponse.setContentType("application/json; charset=utf-8");
try(PrintWriter out = servletResponse.getWriter()){
JSONObject json = new JSONObject();
Map<String, Object> ret = new HashMap<>();
ret.put("retCode", "0");
ret.put("retMsg", "请求token错误!");
json.put("returnValue", ret);
out.writer(json.toJSONString());
out.flush();
return;
} catch (Exception e) {
return;
}
}
}
filterChain.doFilter(request, servletResponse);
}
public String getRequestUri(HttpServletRequest request){
String requestUri = request.getRequestURI();
String contextPath = request.getContextPath();
requestUri = requestUri.substring(requestUri.indexOf(contextPath) + contextPath.length());
return requestUri;
}
@Override
public void destroy(){}
}
文章全手打,有错误的地方麻烦指正,会及时修正!
谢谢大家!
更多推荐
所有评论(0)