How to Create a Java Spring Request Filter

August 2020 | John Binzak
Learn how to create a Java Spring request filter for a sub set of requests.

Overview

In our Java Spring Boot app, sometimes we need to apply logic on a subset of requests. The main logic for incoming request typically lies within our . However what if we want to break out some logic just for requests matching the url ? For this we will use a custom .

Create a Filter

In order to accomplish our subset filter, we will need to create a new class that extends . Then we will add the annotation to specific our url pattern.

@WebFilter(urlPatterns = "/books/*")
public class BooksFilter implements Filter {

}

Implement doFilter

Next we will implement the function. This is the main function for our filter and will house all of our filter logic.

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
    throws IOException, ServletException {

    // continue as normal
    filterChain.doFilter(servletRequest, servletResponse);
}

Check User

Now let's get the current user within our filter.

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {

    // get user
    UserDetails user = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

    // continue as normal
    filterChain.doFilter(servletRequest, servletResponse);
}

Reject Request

What if we want to reject a user? We need to perform our app filter logic, then server an error response. At a high level, all we need to do is exit before call and continue as normal.

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


@WebFilter(urlPatterns = "/books/*")
public class BooksFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
        throws IOException, ServletException {

        // get user
        UserDetails user = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

        // validate
        if(user.getUsername().equalsIgnoreCase("FOO-BAR")){

            // build custom error obj
            CustomApiError apiError = new CustomApiError();
            apiError.setStatus(HttpStatus.TEMPORARY_REDIRECT);
            apiError.setHeader("Temporary Unauthorized");
            apiError.setMessage("No foo bars allowed!");

            // set response type
            ((HttpServletResponse)servletResponse).setStatus(HttpStatus.TEMPORARY_REDIRECT.value());
            ((HttpServletResponse)servletResponse).setContentType(MediaType.APPLICATION_JSON_VALUE);

            // serve error response
            ObjectMapper mapper = new ObjectMapper();
            mapper.writeValue(((HttpServletResponse)servletResponse).getWriter(), apiError);
            return;
        }

        // continue as normal
        filterChain.doFilter(servletRequest, servletResponse);

    }
}

Summary

That's it! It only takes 1 file to create a simple sub filter. We can use this pattern to create multiple filter for an application. Perhaps filter by user permissions or by user subscription level.