4

How i can add custom interceptor (i need log request data when security oauth abort request) before spring security check interceptors.

Igor Fedorov
  • 321
  • 3
  • 17
  • I suspect the only way to do this is to use a org.springframework.web.filter.GenericFilterBean instead of an interceptor and somehow set the ordering of it to happen BEFORE the security thing rejectes the request (if that's even possible) – BoomShaka Jan 01 '22 at 13:27

2 Answers2

1

In case someone else stumbles here...

As I mentioned in my comment, using a Filter instead of an Interceptor SEEMS to work. I would be cautious about this though and do a bit more research as I am a beginner...

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Component;
import org.springframework.web.filter.GenericFilterBean;

import lombok.extern.slf4j.Slf4j;

/**
 * Logs an incoming request method, url and querystring and then continues the chain.
 * NOTE: A HandlerInterceptor only executes AFTER spring security has allowed the request through, hence this approach.
 */
@Slf4j
@Component
public class RequestLoggingFilter extends GenericFilterBean {

    @Override
    public void doFilter(
        ServletRequest request,
        ServletResponse response,
        FilterChain chain
    ) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;

        StringBuilder requestURL = new StringBuilder(httpServletRequest.getRequestURL().toString());
        String queryString = httpServletRequest.getQueryString();
        String url;

        if (queryString == null) {
            url = requestURL.toString();
        } else {
            url = requestURL.append('?').append(queryString).toString();
        }

        log.info("Incoming request: " + httpServletRequest.getMethod()+ " " + url);

        chain.doFilter(request, response);
    }
}

and then I registered it like this:

@EnableWebSecurity
public class SecurityConfig {

    @Autowired
    RequestLoggingFilter requestLoggingFilter;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .addFilterBefore(requestLoggingFilter, UsernamePasswordAuthenticationFilter.class)
            // ... SNIP ...
        return http.build();
    }

I RANDOMLY chose to add it before UsernamePasswordAuthenticationFilter.class, so use with caution. I've no idea really how spring security decides what filters it is going to run (e.g. my app auths with JWT, so UsernamePasswordAuthenticationFilter seems completely pointless to run).

EDIT: https://docs.spring.io/spring-security/site/docs/5.3.9.RELEASE/reference/html5/#servlet-security-filters Maybe adding it BEFORE even the first one (ChannelProcessingFilter) is best?

BoomShaka
  • 1,571
  • 7
  • 27
  • 40
-3

Spring Handler Interceptor

Interceptors working with the HandlerMapping on the framework must implement the HandlerInterceptor interface.

This interface contains three main methods:

prehandle() – called before the actual handler is executed, but the view is not generated yet postHandle() – called after the handler is executed

afterCompletion() – called after the complete request has finished and view was generated These three methods provide flexibility to do all kinds of pre- and post-processing.

And a quick note – the main difference between HandlerInterceptor and HandlerInterceptorAdapter is that in the first one we need to override all three methods: preHandle(), postHandle() and afterCompletion(), whereas in the second we may implement only required methods.

    public class LoggerInterceptor extends HandlerInterceptorAdapter {
       @Override
       public boolean preHandle(
       HttpServletRequest request,
       HttpServletResponse response,Object handler) throws Exception {

       log.info("[preHandle][" + request + "]" + "[" + request.getMethod()
         + "]" + request.getRequestURI() + getParameters(request));

        return true;
       }
    }

Since you're using Spring Boot, I assume you'd prefer to rely on Spring's auto configuration where possible. To add additional custom configuration like your interceptors, just provide a configuration or bean of WebMvcConfigurerAdapter.

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

  @Autowired 
  HandlerInterceptor yourInjectedInterceptor;

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(...)
    ...
    registry.addInterceptor(getYourInterceptor()); 
    registry.addInterceptor(yourInjectedInterceptor);
    // next two should be avoid -- tightly coupled and not very testable
    registry.addInterceptor(new YourInterceptor());
    registry.addInterceptor(new HandlerInterceptor() {
        ...
    });
  }
}
harkesh kumar
  • 833
  • 2
  • 13
  • 35
  • 1
    In Spring Boot 2.x WebMvcConfigurerAdapter is deprecated, Shoud work just implementing the WebMvcConfigurer interfafce instead of extending WebMvcConfigurerAdapter that is deprecated @Configuration public class WebMvcConfig implements WebMvcConfigurer { ... } – Paolo Biavati Jul 22 '20 at 22:17
  • This doesn't answer the question. He is asking how to add an interceptor (for logging) BEFORE the spring security filters kick in and reject a request. A problem I'm trying to solve too. – BoomShaka Jan 01 '22 at 12:56