springboot 统一处理请求非法参数
通过拦截器和过滤器实现,话不多说上代码。
1、重写HttpServletRequestWrapper读取body里面的内容。这里特殊处理了文件上传的内容。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import org.springframework.web.multipart.support.StandardServletMultipartResolver; import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.*; public class RequestWrapper extends HttpServletRequestWrapper { private final String body; public RequestWrapper(HttpServletRequest request) { super(request); String contentType = request.getContentType(); String method = "multipart/form-data"; if (contentType != null && contentType.contains(method)) { // 将转化后的 request 放入过滤链中 request = new StandardServletMultipartResolver().resolveMultipart(request); } StringBuilder stringBuilder = new StringBuilder(); BufferedReader bufferedReader = null; InputStream inputStream = null; try { inputStream = request.getInputStream(); if (inputStream != null) { bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); char[] charBuffer = new char[128]; int bytesRead = -1; while ((bytesRead = bufferedReader.read(charBuffer)) > 0) { stringBuilder.append(charBuffer, 0, bytesRead); } } else { stringBuilder.append(""); } } catch (IOException ex) { } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } } body = stringBuilder.toString(); } @Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes()); ServletInputStream servletInputStream = 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 byteArrayInputStream.read(); } }; return servletInputStream; } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(this.getInputStream())); } public String getBody() { return this.body; } }
2、因为reque里面的内容只能读取一次,需要重写回去。增加ChannelFilter
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; @Component @WebFilter(urlPatterns = "/*",filterName = "channelFilter") public class ChannelFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { ServletRequest requestWrapper = null; if(servletRequest instanceof HttpServletRequest) { requestWrapper = new RequestWrapper((HttpServletRequest) servletRequest); } if(requestWrapper == null) { filterChain.doFilter(servletRequest, servletResponse); } else { filterChain.doFilter(requestWrapper, servletResponse); } } @Override public void destroy() { } }
3、增加拦截器,获取请求的body
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@Component public class ParamInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String method = request.getMethod(); String contentType = request.getContentType() == null ? "" : request.getContentType(); if (HttpMethod.POST.name().equals(method) && !contentType.equals(MediaType.MULTIPART_FORM_DATA_VALUE)) { RequestWrapper requestWrapper = new RequestWrapper(request); String body = requestWrapper.getBody(); testParam(body); } return true; } private void testParam(String param){ try { param = param.replace(" ", ""); param = param.replace("&", ""); param = param.replace("#", ""); param = param.replace(" ", ""); param = param.replace("\"\"", ""); if (param.toLowerCase().contains("<script") || param.contains("<") || param.contains(">") || param.toLowerCase().contains("<html") || param.toLowerCase().contains("<header") || param.toLowerCase().contains("alert") || param.toLowerCase().contains("console") ) { throw new BusinessException("500", "非法参数!"); } } catch (Exception ex) { if (ex instanceof BusinessException) { throw new BusinessException("500", ((BusinessException) ex).getMsg()); } } } }
4、拦截器配置(略)
5、过滤器配置,在启动类上增加@ServletComponentScan注解
6、后续(使用三方工具做敏感词,就不用自己写过滤规则了)
引用
<dependency> <groupId>com.github.houbb</groupId> <artifactId>sensitive-word</artifactId> <version>0.2.0</version> </dependency>
在拦截器里面加入如下代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){ String method = request.getMethod(); String contentType = request.getContentType() == null ? "" : request.getContentType(); if ((HttpMethod.POST.name().equals(method) ||HttpMethod.PUT.name().equals(method) )&& !contentType.equals(MediaType.MULTIPART_FORM_DATA_VALUE)) { RequestWrapper requestWrapper = new RequestWrapper(request); String body = requestWrapper.getBody(); Assert.isTrue(!SensitiveWordHelper.contains(body), MessageFormat.format("参数包含敏感词:{0},请修改后提交!",SensitiveWordHelper.findAll(body, WordResultHandlers.word()))); } return true; }
这样更加科学,具体更多用法参考:https://github.com/houbb/sensitive-word 或者 SpringBoot使用SensitiveWord实现敏感词过滤_sensitive-word-CSDN博客
本文来自博客园,作者:Rolay,转载请注明原文链接:https://www.cnblogs.com/rolayblog/p/18037400