Using Interceptor in a Spring Boot API

Marcos
Javarevisited
Published in
4 min readAug 28, 2021

For several reasons it will be necessary to intercept requests made to the routes of an API, some of them may be:

  • authentication;
  • log input data;
  • generate some information for the request response;
  • and many other things;

In this example api, I’m going to do the following things:

  • validation of some field in the header;
  • permission of an anonymous request (without the validation mentioned above);
  • inclusion of some field in the response header;

The first thing to do is create the project. You can do it here: https://start.spring.io/

I have some other texts that show how to create projects, requests, database crud and I won’t repeat those same things here. I’m going to set up the interceptor and use it.

Important information about the interceptor:

We can use three methods:

  • preHandle() This method is used to perform some action on requests sent to the controller.
  • postHandle() This method is used to perform some action on responses sent to the client.
  • afterCompletion() This method is used to perform actions after request and response.

I started with preHandle() to validate a field that I’m going to call “Authorization” and will be sent in the requests header.

I created a method in the controller with a simple healthcheck:

@Slf4j
@Component
public class Interceptor implements HandlerInterceptor {

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("Request intercepted: " + request.getHeader("Authorization"));
return true;
}

}

And now I registered this interceptor:

@RequiredArgsConstructor
@Configuration
public class ConfigInterceptor extends WebMvcConfigurerAdapter {

private final Interceptor interceptor;

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(interceptor);
}

}

Once this is done, the interceptor is ready for use.

For now, it is just generating a log with the contents of the “Authorization” field, you can see this by calling the health check:

Example using postman:

Log:

Now it’s time to block requests that don’t have a specific value in this header, I modified the preHandle() method in the interceptor class:

@Slf4j
@Component
public class Interceptor implements HandlerInterceptor {

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

if (request.getHeader("Authorization") == null){
log.info("Authorization not sent.");
log.info("Validation NOK.");
return false;
}
else if (request.getHeader("Authorization").equals("Test")) {

log.info("Validation OK.");
return true;
} else {
log.info("Validation NOK.");
return false;
}

}

}

Result sending the same GET through postman but without the header:

And the expected “200 ok” was not sent to the client.

Result sending the same GET by postman with an invalid header:

In this case, the expected “200 ok” was not sent to the client either.

Now the result for the request that sends the header with the right value:

And the 200 ok was sent to the client:

Okay, we have a field in the header that when validated allows or not the success of a request. But this route is a health check, it doesn’t expose anything sensitive and in theory, it can be used without this check.

The result of this will be the validation of the header in all other routes of the API except “/healthcheck”.

For this I made a few steps:

I created an enum:

public enum ValidationType {

ANNONYMOUS ("Online");

String value;

ValidationType(String value){
this.value = value;
}

public String getValue(){
return value;
}

}

I used this annotation on the controller:

@RestController
public class HealthCheck {

@AllowAnnonymous
@GetMapping(value = "/healthcheck")
public String getHealthCheck(){
return "200 ok";
}

}

And I changed the preHandle():

@Slf4j
@Component
public class Interceptor implements HandlerInterceptor {

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

final AllowAnnonymous allowAnnonymous = ((HandlerMethod)handler).getMethod().getAnnotation((AllowAnnonymous.class));

if(allowAnnonymous != null){
return true;
}

if (request.getHeader("Authorization") == null){
response.addHeader("Interceptor", "Authorization not sent");
log.info("Authorization not sent.");
log.info("Validation NOK.");
return false;
}
else if (request.getHeader("Authorization").equals("Test")) {
response.addHeader("Interceptor", "Authorization OK");
log.info("Validation OK.");
return true;
} else {

log.info("Validation NOK.");
return false;
}

}
}

In the postman you can see the header I put in responses:

This is a basic example that needs to be refactored but it also gives an idea of ​​how to use an interceptor.

I hope it helps.

I left the sources here: https://github.com/mmarcosab/interceptor-example

--

--

Marcos
Javarevisited

I study software development and I love memes.