创建一个 DemoFilter
package com.zdran.springboot.filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import java.io.IOException;
/**
* Create by ranzd on 2018/8/9
*
* @author cm.zdran@gmail.com
*/
public class DemoFilter implements Filter{
private Logger logger = LoggerFactory.getLogger(DemoFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
logger.info("初始化 DemoFilter ");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
logger.info("拦截到参数:{}", servletRequest.getParameterMap());
if (true) {
filterChain.doFilter(servletRequest,servletResponse);
}
logger.info("拦截到参数。请求被拦截");
}
@Override
public void destroy() {
logger.info("销毁 DemoFilter ");
}
}
核心的方法是 doFilter
,可以在这个方法内对参数进行校验,通过servletRequest
可以获取到请求中的参数。根据参数进行拦截。
filterChain.doFilter(servletRequest,servletResponse);
如果调用了这行代码说明不拦截这次请求,如果没有调用这行代码,这次请求请求将被拦截。
将这个Filter注入到容器中,创建 FilterConfig 类
@Configuration
public class FilterConfig {
private Logger logger = LoggerFactory.getLogger(FilterConfig.class);
@Bean
public FilterRegistrationBean xssFilterRegistrationBean() {
logger.info("初始化 DemoFilter 过滤器 Bean");
FilterRegistrationBean<Filter> initXssFilterBean = new FilterRegistrationBean<>();
initXssFilterBean.setFilter(new DemoFilter());
initXssFilterBean.setOrder(1);
initXssFilterBean.setEnabled(true);
initXssFilterBean.addUrlPatterns("/*");
initXssFilterBean.setDispatcherTypes(DispatcherType.REQUEST);
return initXssFilterBean;
}
}
setOrder方法可以对这个 Filter 设置一个优先级,这个值越小,越先被执行。尽量不要与其他的 Filter 冲突
有些时候我们可能需要对参数进行修改,比如XSS过滤,防SQL注入等。这个时候我们可以通过HttpServletRequestWrapper
来对参数进行修改。 创建 DemoHttpServletRequestWrapper
。通过重写这个类的一些方法来对参数进行修改。
package com.zdran.springboot.filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.util.Map;
/**
* Create by ranzd on 2018/8/9
*
* @author cm.zdran@gmail.com
*/
public class DemoHttpServletRequestWrapper extends HttpServletRequestWrapper {
private Logger logger = LoggerFactory.getLogger(DemoHttpServletRequestWrapper.class);
public DemoHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getHeader(String name) {
String value = super.getHeader(name);
logger.info("获取 Header 中的参数:{}", value);
return value;
}
@Override
public String getParameter(String name) {
String value = super.getParameter(name);
logger.info("获取 getParameter 中的参数:{}", value);
return value;
}
@Override
public Map<String, String[]> getParameterMap() {
Map<String, String[]> map = super.getParameterMap();
logger.info("获取 getParameterMap 中的参数:{}", map);
return map;
}
@Override
public HttpSession getSession() {
HttpSession session = super.getSession();
logger.info("获取 getCookies 中的cookie:{}", session);
return session;
}
@Override
public Object getAttribute(String name) {
Object obj = super.getAttribute(name);
logger.info("获取 getCookies 中的cookie:{}", obj);
return obj;
}
@Override
public String[] getParameterValues(String name) {
String[] value = super.getParameterValues(name);
logger.info("获取 getParameter 中的参数:{}", value);
return value;
}
@Override
public ServletInputStream getInputStream() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(super.getInputStream()));
StringBuilder resultBuilder = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
resultBuilder.append(line);
}
String result = resultBuilder.toString();
logger.info("获取 getInputStream 中的参数:{}", result);
return new WrappedServletInputStream(new ByteArrayInputStream(result.getBytes()));
}
/**
* 读取 RequestBody 中的参数时需要重新再次写入到流中,
* 否则在 Controller 中会读取不到参数。
*/
private class WrappedServletInputStream extends ServletInputStream {
public void setStream(InputStream stream) {
this.stream = stream;
}
private InputStream stream;
public WrappedServletInputStream(InputStream stream) {
this.stream = stream;
}
@Override
public int read() throws IOException {
return stream.read();
}
@Override
public boolean isFinished() {
return true;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
}
}
}
注意: 在读取 RequestBody中的参数的时候需要用 getInputStream
方法,而且读取结束后,必须再次向该流中写入,否则Controller将读取不到参数。