SpringBoot:拦截器与过滤器
一、拦截器与过滤器
过滤器和拦截器。这两者在功能方面很类似,但是在具体技术实现方面,差距还是比较大的。在分析两者的区别之前,我们先理解一下AOP的概念,AOP不是一种具体的技术,而是一种编程思想。在面向对象编程的过程中,我们很容易通过继承、多态来解决纵向扩展。 但是对于横向的功能,比如,在所有的service方法中开启事务,或者统一记录日志等功能,面向对象的是无法解决的。所以AOP——面向切面编程其实是面向对象编程思想的一个补充。而我们今天讲的过滤器和拦截器都属于面向切面编程的具体实现。
而两者的主要区别包括以下几个方面:
- Filter是依赖于Servlet容器,属于Servlet规范的一部分,而拦截器则是独立存在的,可以在任何情况下使用。
- Filter的执行由Servlet容器回调完成,而拦截器通常通过动态代理的方式来执行。
- Filter的生命周期由Servlet容器管理,而拦截器则可以通过IoC容器来管理,因此可以通过注入等方式来获取其他Bean的实例,因此使用会更方便。
二、过滤器的配置
/**
* 防止SQL注入
*/
@Configuration
@WebFilter(urlPatterns = "/*", filterName = "SQLInjection")
public class SQLInjectionFilterServlet implements Filter {
private static final Logger log = LoggerFactory.getLogger(SQLInjectionFilterServlet.class);
private String regularExpression;
public SQLInjectionFilterServlet() {
}
public void init(FilterConfig filterConfig) throws ServletException {
regularExpression = "(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|" + "(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)";
log.info("######### regularExpression={}", regularExpression);
}
/**
* 如果输入“ ' ”,“ ; ”,“ -- ”这些字符,可以考虑将这些字符转义为html转义字符 “'”转义字符为:' “;”转义字符为:;
* “--”转义字符为:--
*/
@SuppressWarnings("rawtypes")//抑制多类型的警告
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
String requestUrl = req.getRequestURI();
String contextPath = req.getContextPath();
// 获取剥离contextPath的url路径
requestUrl = requestUrl.substring(requestUrl.indexOf(contextPath) + contextPath.length());
//System.out.println("requestUrl= " + requestUrl);
//获取http提交过来的数据
Map<String, String[]> parameterMap = servletRequest.getParameterMap();
Iterator<Map.Entry<String, String[]>> it = parameterMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String[]> entry = it.next();
String[] value = entry.getValue();
for (int i = 0; i < value.length; i++) {
if (null != value[i] && value[i].matches(regularExpression)) {
log.info("*******疑似SQL注入攻击!参数名称:{};录入信息:{}", entry.getKey(), value[i]);
//将消息传出在web容器内部
servletRequest.setAttribute("err", "您输入的参数有非法字符,请输入正确的参数!");
servletRequest.setAttribute("pageUrl", req.getRequestURI());
//跳转到指定的error页面
//String errorPage = servletRequest.getServletContext().getContextPath() + "/error";
//servletRequest.getRequestDispatcher(errorPage).forward(servletRequest, servletResponse);
return;
}
}
}
//将请求转发给过滤器链下一个filter
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {}
}