Spring Boot filter incoming requests based on IP

Spring Security Filter

In one of the previous articles, we demonstrated how to restrict incoming requests based on IP addresses. In that article, we leveraged Spring Boot Security to get the job done by manipulating Spring Security config. A cleaner solution is to move the logic to a Spring filter. In this article, we explain how to filter incoming requests based on IP addresses in Spring Boot by using Spring filters.

A realistic use case

Let’s say we want to make a Telegram Bot and register it with the Telegram webhook. So that Telegram can call the endpoint on any action triggered. But on the other hand, we don’t want anybody impersonating Telegram and calling our bot application to do whatever he wants. For that, we want only to accept requests that are coming from Telegram servers only. The subnet IP addresses of the Telegram servers are known to us (149.154.160.0/20, 91.108.4.0/22 in fact).

Spring Boot filter incoming requests based on IP
The workflow

Implementation

To implement what was explained in the previous section, we must create a Spring Boot filter to check incoming requests based on IP. It should check whether the request IP matches with the Telegram subnet. This filter should be executed only once per request. So it makes sense to extend from OncePerRequestFilter that guarantees one execution per request. A simple implementation looks like the below,

package com.madadipouya.telegram.sample.filter;

import org.springframework.security.web.util.matcher.IpAddressMatcher;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class RequestTelegramOriginatedFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        if (matches(request, "149.154.160.0/20") || matches(request, "91.108.4.0/22")) {
            filterChain.doFilter(request, response);
        }
    }

    private boolean matches(HttpServletRequest request, String subnet) {
        IpAddressMatcher ipAddressMatcher = new IpAddressMatcher(subnet);
        return ipAddressMatcher.matches(request);
    }
}

As you can see, we use IpAddressMatcher to see whether the IP matches or not. And the package is also part of Spring Security. So regardless of the approach, we need to use Spring Security.

It is worth mentioning that we don’t necessarily need to use the Spring filter. Instead, we can Servlet filter as well.

Conclusion

In this tutorial, we demonstrated another approach to restrict requests based on IP address by using a Spring Boot filter. In comparison to Spring Security, this implementation is cleaner. It intercepts requests at a much higher level.

Inline/featured images credits