上节已经介绍了过滤器的使用方法,现在我们来看下实际场景中,如何使用过滤器过滤请求的参数中的敏感信息,主要针对get、post两种请求方式过滤。
1. get请求参数过滤
get请求,可以从request中拿到请求参数,看参数中是否包含敏感信息,假设敏感信息是"傻瓜"
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
boolean flag = true;
String badInfo = "傻瓜";
if (httpServletRequest.getMethod().equals(RequestMethod.GET.name())) {
Map<String, String[]> parameterMap = httpServletRequest.getParameterMap();
if (!MapUtils.isEmpty(parameterMap)) {
flag =!parameterMap.entrySet().stream().anyMatch(entry -> Arrays.toString(entry.getValue()).contains(badInfo));
if (!flag) {
servletResponse.setContentType("application/json; charset=UTF-8");
PrintWriter out = servletResponse.getWriter();
ResultResponse resultResponse = new ResultResponse();
out.println(JSON.toJSONString(ResultResponse.fail("-9999", "参数包含敏感信息")));
out.flush();
} else {
filterChain.doFilter(servletRequest, servletResponse);
}
} else {
filterChain.doFilter(servletRequest, servletResponse);
}
}
测试,访问一个get接口,参数为"笨蛋",结果如下
2. post请求参数过滤
post请求参数就不能直接获取了,要通过输入流InputStream获取,但是这里有一个坑
public String getParm(HttpServletRequest request) {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(request.getInputStream(), "UTF-8"));
} catch (IOException e) {
}
String line = null;
StringBuilder sb = new StringBuilder();
try {
while ((line = br.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
}
return sb.toString();
}
这个方法就是从post请求中获取参数,参数可以正常获取,但是访问却会报错
错误说缺少请求体,但是我们明明有传参,可知从InputStream获取参数只能获取一次,因为InputStream内部有个pos指针,指向下次要读取的起始位置,由于已经读取了一次,指针位置已指向末端,ServletInputStream没有重写reset方法,无法重置pos指针指向位置,所以当读取完后将无法继续读取
因此我们可以请求参数以byte[]形式存起来,新建class继承HttpServletRequestWrapper
public class RequestWrapper extends HttpServletRequestWrapper {
private String body;
public RequestWrapper(HttpServletRequest request) throws IOException {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
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) {
throw ex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
throw ex;
}
}
}
body = stringBuilder.toString();
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
ServletInputStream servletInputStream = new ServletInputStream() {
public boolean isFinished() {
return false;
}
public boolean isReady() {
return false;
}
public void setReadListener(ReadListener readListener) {}
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
return servletInputStream;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream(),"UTF-8"));
}
public String getBody() {
return this.body;
}
}
过滤器的doFilter方法如下
} else if (httpServletRequest.getMethod().equals(RequestMethod.POST.name())) {
RequestWrapper requestWrapper = new RequestWrapper(httpServletRequest);
if(requestWrapper == null) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
String body = requestWrapper.getBody();
flag = !body.contains(badInfo);
if (!flag) {
servletResponse.setContentType("application/json; charset=UTF-8");
PrintWriter out = servletResponse.getWriter();
ResultResponse resultResponse = new ResultResponse();
out.println(JSON.toJSONString(ResultResponse.fail("-9999"
, "参数包含敏感信息")));
out.flush();
} else {
filterChain.doFilter(requestWrapper, servletResponse);
}
}
} else {
filterChain.doFilter(servletRequest, servletResponse);
}
访问一个post接口,包含敏感信息’笨蛋’