SpringBoot:拦截器与过滤器

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() {}
}

你可能感兴趣的:(后端,过滤器)