Why Your Public API Lacks IP Blacklist/Whitelist Protection (And How to Fix It)

The article explains the importance of IP black‑ and white‑listing for external APIs, compares implementing the filters inside a Spring Boot project versus configuring them in Nginx, and provides step‑by‑step code and configuration examples for both approaches.

Shepherd Advanced Notes
Shepherd Advanced Notes
Shepherd Advanced Notes
Why Your Public API Lacks IP Blacklist/Whitelist Protection (And How to Fix It)

1. Overview

IP black‑ and white‑listing is a common network‑security mechanism that controls access to resources by denying IPs on a blacklist and allowing IPs on a whitelist, thereby preventing unauthorized access and improving system security for publicly exposed APIs.

Implementation options include adding the logic directly in the application code or configuring it in Nginx; each has distinct advantages and drawbacks.

2. Implementing IP Black/White List in a Spring Boot Project

Advantages

More flexible – custom logic can be based on user roles, request paths, etc.

Extensible – can be combined with other security features.

Easier debugging – logs are generated inside the application.

Disadvantages

Potential performance impact if the list is large or frequently updated.

Additional development effort is required.

Implementation steps

public class IpUtil {
    private static final String UNKNOWN = "unknown";
    public static String getIpAddress() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String ip = request.getHeader("x-forwarded-for");
        if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isBlank(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        // Multiple proxies: the first IP is the client IP
        if (StringUtils.isNotBlank(ip) && ip.indexOf(',') > 0) {
            ip = ip.substring(0, ip.indexOf(","));
        }
        return ip;
    }
}
@Component
@Slf4j
public class IpAccessInterceptor implements HandlerInterceptor {
    @Value("${ip.black}")
    private Set<String> blackIpList;
    @Value("${ip.white}")
    private Set<String> whiteIpList;
    private static final String LOCAL = "127.0.0.1";
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String ip = IpUtil.getIpAddress();
        if (Objects.equals(ip, LOCAL)) {
            return true; // allow localhost
        }
        if (blackIpList.contains(ip)) {
            log.info("ip:{} is in blacklist, rejecting", ip);
            return false;
        }
        if (!whiteIpList.contains(ip)) {
            log.info("ip:{} not in whitelist, rejecting", ip);
            return false;
        }
        return true; // passed
    }
}
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Resource
    private IpAccessInterceptor ipAccessInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(ipAccessInterceptor).addPathPatterns("/**");
    }
}

Test controller:

@GetMapping("/filter")
public String testFilter() {
    log.info("controller method executed");
    return "hello";
}

Configuration file (application.yml) snippet:

ip:
  black: 10.0.0.10,10.0.0.18,10.33.194.35
  white: 10.33.194.36,10.33.194.10

When calling http://10.33.194.35:8080/test/filter, the console logs:

INFO  com.shepherd.basedemo.interceptor.IpAccessInterceptor preHandle : ip:10.33.194.35 is in blacklist, rejecting...

3. Configuring IP Black/White List in Nginx

Advantages

High performance – filtering occurs at the network layer.

Simple and quick – only edit the Nginx config file.

Reduces load on the application server.

Disadvantages

Static configuration – cannot adapt to business‑logic changes.

Debugging and logging are harder.

Example Nginx configuration (add inside the http block):

http {
    ...
    # whitelist
    allow 192.168.1.100;
    allow 192.168.1.101;
    # blacklist
    deny 192.168.1.200;
    deny 192.168.1.201;
    server {
        listen 80;
        server_name example.com;
        location / {
            allow all;   # if IP not in whitelist and not in blacklist, deny
            deny all;
            proxy_pass http://your_backend_server;
        }
    }
    ...
}

Reload the configuration with nginx -s reload.

4. Conclusion

Whether you choose an application‑level interceptor or an Nginx rule depends on flexibility versus performance needs. Both methods can effectively block unauthorized IPs for external APIs. Remember to obtain the outbound IP of the client system (e.g., via curl ip.me) and keep the whitelist stable; otherwise dynamic IPs make blacklist/whitelist management difficult.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Spring BootsecurityinterceptorNginxIP whitelistIP blacklist
Shepherd Advanced Notes
Written by

Shepherd Advanced Notes

Dedicated to sharing advanced Java technical insights, daily work snippets, and the power of persistent effort.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.