在Spring Web应用程序中排除过滤器的URL

Excluding URLs for a Filter in a Spring Web Application

1.概述

大多数Web应用程序都有执行诸如请求日志记录,验证或身份验证之类的操作的用例。而且,此类任务通常在一组HTTP端点之间共享。

好消息是,Spring Web框架为此提供了一种过滤机制。

在本教程中,我们将学习如何针对给定的URL集在执行中包括或排除执行过滤器样式的任务。

2.过滤特定的URL

假设我们的Web应用程序需要记录一些有关其请求的信息,例如它们的路径和内容类型。一种方法是创建日志记录过滤器。

2.1。记录过滤器

首先,让我们在LogFilter类中创建日志记录过滤器,该类扩展了OncePerRequestFilter类并实现doFilterInternal方法:

1
2
3
4
5
6
7
8
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
  FilterChain filterChain) throws ServletException, IOException {
    String path = request.getRequestURI();
    String contentType = request.getContentType();
    logger.info("Request URL path : {}, Request content type: {}", path, contentType);
    filterChain.doFilter(request, response);
}

2.1。规则过滤器

假设我们只需要对某些URL模式(即/ health,/ faq / *)执行日志记录任务。为此,我们将使用FilterRegistrationBean注册日志记录过滤器,使其仅匹配所需的URL模式:

1
2
3
4
5
6
7
@Bean
public FilterRegistrationBean<LogFilter> logFilter() {
    FilterRegistrationBean<LogFilter> registrationBean = new FilterRegistrationBean<>();
    registrationBean.setFilter(new LogFilter());
    registrationBean.addUrlPatterns("/health","/faq/*");
    return registrationBean;
}

2.2。排除规则过滤器

如果要从执行日志记录任务中排除URL,可以通过两种方式轻松实现:

  • 对于新网址,请确保它与过滤器使用的网址格式不匹配

  • 对于较早启用了日志记录的旧URL,我们可以修改URL模式以排除此URL

  • 3.筛选所有可能的URL

    我们很轻松地满足了我们以前的用例,只需很少的工作即可在LogFilter中包括URL。但是,如果过滤器使用通配符(*)来匹配所有可能的URL模式,则将变得更加棘手。

    在这种情况下,我们需要自己编写包含和排除逻辑。

    3.1。 CustomFilter

    客户端可以使用请求标头将有用的信息发送到服务器。假设我们的Web应用程序当前仅在美国运行,这意味着我们不想处理来自其他国家的请求。

    让我们进一步想象一下,我们的Web应用程序通过X-Country-Code请求标头指示语言环境。因此,每个请求都包含此信息,并且我们有明确的理由使用过滤器。

    让我们实现一个用于检查标题的过滤器,拒绝不符合我们条件的请求:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
          FilterChain filterChain) throws ServletException, IOException {

        String countryCode = request.getHeader("X-Country-Code");
        if (!"US".equals(countryCode)) {
            response.sendError(HttpStatus.BAD_REQUEST.value(),"Invalid Locale");
            return;
        }

        filterChain.doFilter(request, response);
    }

    3.2。筛选注册

    首先, 让我们使用 星号(*)通配符来注册我们的过滤器 以匹配所有可能的URL模式:

    1
    2
    3
    4
    5
    6
    7
    @Bean
    public FilterRegistrationBean<HeaderValidatorFilter> headerValidatorFilter() {
        FilterRegistrationBean<HeaderValidatorFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new HeaderValidatorFilter());
        registrationBean.addUrlPatterns("*");
        return registrationBean;
    }

    稍后,我们可以排除执行验证区域设置请求标头信息的任务不需要的URL模式。

    3.3。网址排除

    再次假设我们在/ health处有一个Web路由,可用于对应用程序进行ping-pong运行状况检查。

    到目前为止,所有请求都将触发我们的过滤器。我们可以猜测,这是我们进行健康检查的开销。

    因此,通过从过滤器主体中排除/ health请求,可以简化它:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
          throws ServletException, IOException {
        String path = request.getRequestURI();
        if ("/health".equals(path)) {
            filterChain.doFilter(request, response);
            return;
        }

        String countryCode = request.getHeader("X-Country-Code");
        // ... same as before
    }

    我们必须注意,在doFilter方法中添加此自定义逻辑会导致/ health端点与我们的过滤器之间的耦合。因此,这不是最佳方法,因为如果更改运行状况检查端点而没有在doFilter方法内进行相应更改,则可能破坏过滤逻辑。

    4。结论

    在本教程中,我们探讨了如何在两种情况下从Spring Boot Web应用程序的servlet过滤器中排除URL模式:日志记录和请求标头验证。

    此外,我们了解到,为使用*通配符匹配所有可能的URL模式的过滤器排除一组特定的URL变得很棘手。

    与往常一样,该教程的完整源代码可在GitHub上获得。