FilterRegistrationBean has a setUrlPatterns for customizing the URL patterns that the filter will be registered against. Sometimes, setting exclusion pattern is desired more than inclusion pattern. For example, I want to be able to say "Exclude all URLs that start with monitoring, thank you", vs. listing each endpoint that the service may support.
This ticket is to provide support for exclude URL patterns. If both exclude and include patterns exist, and there's a conflict, exclude should win as usually is the case. I understand that the matching is done by the servlet container but I'm still hoping that there's some way to do this.
Comment From: asarkar
I found a way to do this. OncePerRequestFilter has a shouldNotFilter(HttpServletRequest request) method, so I could do:
@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
return excludeUrlPatterns.stream()
.anyMatch(p -> pathMatcher.match(p, request.getServletPath()));
}
where excludeUrlPatterns is a Collection<String> and pathMatcher is an AntPathMatcher.
The catch is that this happens after the filter is applied using whatever pattern has been specified in the FilterRegistrationBean (or the default /*).
Comment From: wilkinsona
Thanks for sharing your approach. I think something like that is your best option here as the Servlet API doesn't provide a way to configure URL pattern exclusions. You can only add inclusions.
Comment From: VNYoeri
The solution provided by @asarkar works perfect! Thanks!
Mind, you may still have to add the necessary variables to your method (or at class-level) Collection<String> excludeUrlPatterns = new ArrayList<>(); and initialize it like this: excludeUrlPatterns.add(AppConstants.API_BASE + "/auth/**"); as well as AntPathMatcher pathMatcher = new AntPathMatcher();.
I'm just adding this for people that are new to this technology or to developing in general (like me at the moment :) ).
Comment From: mrCalmdow
can i use patterns like this:filterRegistrationBean.addUrlPatterns("/v1/*/member/*"); OR filterRegistrationBean.addUrlPatterns("/*/v1/member/*");to filter URLs like http://localhost:8080/v1/18682256/member/articles OR http://localhost:8080/18682256/v1/member/articles?
Comment From: wilkinsona
@mrCalmdow This issue is closed and we don't use the issue tracker for questions. The patterns work in the way that is described by the Servlet specification. If you need further help, please ask on Stack Overflow.
Comment From: mrCalmdow
thanks for your answers.
Comment From: ricardo-ropelli
Also could be done like this:
package br.com.actaholding.erpmiddleware.authorizer.filter;
@Configuration
public class CommonsRequestLoggingFilterConfig {
private static final List<String> EXCLUDE_URL = Arrays.asList("/healthcheck", "/health-check");
@Bean
public CommonsRequestLoggingFilter logFilter() {
CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter() {
@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
return EXCLUDE_URL.stream().anyMatch(exclude -> exclude.equalsIgnoreCase(request.getServletPath()));
}
};
/*filter.set properties you need*/
return filter;
}
}
log4j2.xml
<Logger name="br.com.actaholding.erpmiddleware.authorizer.filter.CommonsRequestLoggingFilterConfig$1" level="${env:LOGGING_REQUEST_LEVEL:-INFO}">
<AppenderRef ref="ConsoleAppender"/>
</Logger>
The '$1' after class name is because the anonymous / inner class.
Remember set env var 'LOGGING_REQUEST_LEVEL' to DEBUG
Comment From: abyrne133
You could consider (probably shouldn't!) manually implementing the exclusion logic. Here's an spring boot example, not tested.
@Component
public class ExampleFilter implements Filter {
@Value("${filter.url-exclusion-list}")
private List<String> urlExclusionList;
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String requestUrl = httpServletRequest.getRequestURL().toString().toLowerCase();
AtomicBoolean ignoreUrl = new AtomicBoolean(false);
urlExclusionList.forEach((url) -> {
if(requestUrl.contains(url.toLowerCase())){
ignoreUrl.set(true);
}
});
if(!ignoreUrl.get()){
// "before" filter logic here
}
filterChain.doFilter(servletRequest, servletResponse);
if(!ignoreUrl.get()){
// "after" filter logic here
}
}
}
Comment From: jhonatanbatista1991
The combination of solutions provided by @asarkar and @VNYoeri works great ❤️
@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
AntPathMatcher pathMatcher = new AntPathMatcher();
List<String> excludeUrlPatterns = List.of(
"/v1/EXAMPLE_YOUR_URL_TO_NOT_FILTER",
"/v1/EXAMPLE_YOUR_URL_TO_NOT_FILTER"
);
return excludeUrlPatterns
.stream()
.anyMatch(p -> pathMatcher.match(p, request.getServletPath()));
}