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.
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 /*
).
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.
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 :) ).
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
?
@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.
thanks for your answers.
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
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
}
}
}
Most helpful comment
I found a way to do this.
OncePerRequestFilter
has ashouldNotFilter(HttpServletRequest request)
method, so I could do:where
excludeUrlPatterns
is aCollection<String>
andpathMatcher
is anAntPathMatcher
.The catch is that this happens _after_ the filter is applied using whatever pattern has been specified in the
FilterRegistrationBean
(or the default/*
).