Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exception handling in Spring GenericFilterBean

I have implemented token based authentication(without spring security). So in GenericFilterBean, it checks and claims token.

public class MyTokenFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws MyAuthException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        if (!"OPTIONS".equals(request.getMethod())) {

            String authHeader = request.getHeader("Authorization");

            if (authHeader == null || !authHeader.startsWith("Token ")) {
                throw new MyAuthException("Authorization header needed"); // Should return custom http status response like 400
            }

            String token = authHeader.substring(6);

            try {
                claimToken(token);
            } catch (Exception e) {
                throw new MyAuthException("Invalid token."); // Should return custom http status response like 401
            }

        }

        chain.doFilter(req, res);

    }

}

So in this filter it seems all okay. But I need to send response with different Http Statutes with a json. I am able to use ResponseEntitiyExceptionHandler with @ControllerAdvice. So I can handle exceptions in my controllers.

@ControllerAdvice
public class MyPrettyExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(MyAuthException.class)
    @ResponseBody
    public ResponseEntity<Object> handleCustomException(HttpServletRequest req, MyAuthException ex) {
        Map<String, String> responseBody = new HashMap<>();
        responseBody.put("error", "true");
        responseBody.put("message", ex.getMessage());
        return new ResponseEntity<Object>(responseBody, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

I know how it works and which order Filter and controllers and their exceptions(filters do their job before controllers, so they're not same scope with controllers). So naturally I can't handle filter's exceptions with ControllerAdvice.

So what is the efficient way to handle exceptions in Filters(like my example way)? Can you suggest me another way about it?

like image 309
İlker Korkut Avatar asked Jul 18 '15 22:07

İlker Korkut


People also ask

How is exception handling done in spring boot?

Exception HandlerThe @ExceptionHandler is an annotation used to handle the specific exceptions and sending the custom responses to the client. Define a class that extends the RuntimeException class. You can define the @ExceptionHandler method to handle the exceptions as shown.

How do you handle security exceptions in spring?

Spring security exceptions can be directly handled by adding custom filters and constructing the response body. To handle these exceptions at a global level via @ExceptionHandler and @ControllerAdvice, we need a custom implementation of AuthenticationEntryPoint.

What is the use of AuthenticationEntryPoint?

AuthenticationEntryPoint is used to send an HTTP response that requests credentials from a client. Sometimes a client will proactively include credentials such as a username/password to request a resource.


1 Answers

You should use response.sendError for send error code and status :

public class MyTokenFilter extends GenericFilterBean {

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

        if (!"OPTIONS".equals(request.getMethod())) {

            String authHeader = request.getHeader("Authorization");
            if (authHeader == null || !authHeader.startsWith("Token ")) {
                //throw new MyAuthException("Authorization header needed"); // Should return custom http status response like 400
                response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Authorization header needed");
                return ;
            }

            String token = authHeader.substring(6);
            try {
                claimToken(token);
            } catch (Exception e) {
                //throw new MyAuthException("Invalid token."); // Should return custom http status response like 401
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid token.");
                return ;
            }
        }
        chain.doFilter(req, res);
    }
}
like image 82
vit Avatar answered Oct 02 '22 08:10

vit