I've a simple filter just to check if a request contains a special header with static key - no user auth - just to protect endpoints. The idea is to throw an AccessForbiddenException
if the key does not match which then will be mapped to response with a class annotated with @ControllerAdvice
. However I can't make it work. My @ExceptionHandler
isn't called.
ClientKeyFilter
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Controller
import javax.servlet.*
import javax.servlet.http.HttpServletRequest
@Controller //I know that @Component might be here
public class ClientKeyFilter implements Filter {
@Value('${CLIENT_KEY}')
String clientKey
public void init(FilterConfig filterConfig) {}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
req = (HttpServletRequest) req
def reqClientKey = req.getHeader('Client-Key')
if (!clientKey.equals(reqClientKey)) {
throw new AccessForbiddenException('Invalid API key')
}
chain.doFilter(req, res)
}
public void destroy() {}
}
AccessForbiddenException
public class AccessForbiddenException extends RuntimeException {
AccessForbiddenException(String message) {
super(message)
}
}
ExceptionController
@ControllerAdvice
class ExceptionController {
static final Logger logger = LoggerFactory.getLogger(ExceptionController)
@ExceptionHandler(AccessForbiddenException)
public ResponseEntity handleException(HttpServletRequest request, AccessForbiddenException e) {
logger.error('Caught exception.', e)
return new ResponseEntity<>(e.getMessage(), I_AM_A_TEAPOT)
}
}
Where I'm wrong? Can simple servlet filter work with spring-boot's exception mapping?
A filter is an object that is invoked at the preprocessing and postprocessing of a request on the server, i.e., before and after the execution of a servlet for filtering the request. Filter API (or interface) includes some methods which help us in filtering requests.
So to avoid this, we add Filters on the Server side. Note: The user-defined servlet filter is pluggable, i.e., its entry is defined in the web.xml file, if we remove the entry of the filter from the web.xml file, it will be removed automatically and we don’t need to change the servlet. Authentication and authorization of requests for resources.
doFilter () method takes three arguments – ServletRequest, ServletResponse, FilterChain. With the help of FilterChain, we can forward the request after successful authentication. Create a class that implements the Filter interface and overrides all its methods, i.e., init (), doFilter (), destroy ().
These stages are similar to a servlet’s Instantiate, Initialize, Filter, destroy. The filter is used to pre-process the request and Post-processing the response. A Filter is a java object that performs the Filtering task on either the request to a resource or on the response from a resource or both.
As specified by the java servlet specification Filter
s execute always before a Servlet
is invoked. Now a @ControllerAdvice
is only useful for controller which are executed inside the DispatcherServlet
. So using a Filter
and expecting a @ControllerAdvice
or in this case the @ExceptionHandler
, to be invoked isn't going to happen.
You need to either put the same logic in the filter (for writing a JSON response) or instead of a filter use a HandlerInterceptor
which does this check. The easiest way is to extend the HandlerInterceptorAdapter
and just override and implement the preHandle
method and put the logic from the filter into that method.
public class ClientKeyInterceptor extends HandlerInterceptorAdapter {
@Value('${CLIENT_KEY}')
String clientKey
@Override
public boolean preHandle(ServletRequest req, ServletResponse res, Object handler) {
String reqClientKey = req.getHeader('Client-Key')
if (!clientKey.equals(reqClientKey)) {
throw new AccessForbiddenException('Invalid API key')
}
return true;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With