Implementing Internal‑Only APIs with Microservice Isolation, Gateway Whitelist, and AOP in Java

This article explains how to restrict certain APIs to internal network calls by comparing three approaches—microservice isolation, gateway + Redis whitelist, and gateway + AOP—and provides a complete Java implementation of the AOP solution with code examples.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Implementing Internal‑Only APIs with Microservice Isolation, Gateway Whitelist, and AOP in Java

When developing business services, you may encounter the need for interfaces that cannot be exposed externally and must be called only between internal services. This article examines three feasible solutions and selects one for detailed implementation.

1. Internal‑External Interface Microservice Isolation

Separate externally exposed interfaces and internally exposed interfaces into two microservices: one service whose APIs are all public, and another service whose APIs are only callable within the internal network.

This approach requires an additional microservice that aggregates all internal‑only business interfaces, acting as a request forwarder. While it isolates concerns, it adds system complexity, increases latency, and raises maintenance costs.

2. Gateway + Redis Whitelist Mechanism

Maintain a whitelist of allowed interfaces in Redis. When an external request reaches the gateway, the gateway checks Redis; if the interface is on the whitelist it is allowed, otherwise it is rejected.

Advantages: zero intrusion into business code, only whitelist maintenance is needed. Drawbacks: continuous effort to maintain the whitelist, often requiring ticket submissions; each request incurs a whitelist lookup, adding response time, and the cost‑benefit ratio is low because most traffic is legitimate.

3. Gateway + AOP Approach

Instead of checking the whitelist at the gateway, this method determines the request source and delegates the check to the business side, reducing gateway load and improving response speed.

External requests always pass through the gateway, while internal service‑to‑service calls bypass it (e.g., via Kubernetes Service). By adding a custom header (e.g., from=public) at the gateway, business services can inspect the header: if present, the request is external; if absent, it is internal.

The business side uses an AOP aspect and a custom annotation to enforce internal‑only access, allowing developers to mark APIs with @OnlyIntranetAccess. This distributes access control, eliminates gateway bottlenecks, and improves code readability, though it introduces some code intrusion that can be mitigated with annotations.

Specific Implementation

First, add the external identifier header in the gateway filter:

@Component
public class AuthFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        return chain.filter(
            exchange.mutate().request(
                exchange.getRequest().mutate()
                    .header("id", "")
                    .header("from", "public")
                    .build())
                .build()
        );
    }
    @Override
    public int getOrder() {
        return 0;
    }
}

Next, create the AOP aspect and annotation for internal‑only access:

@Aspect
@Component
@Slf4j
public class OnlyIntranetAccessAspect {
    @Pointcut("@within(org.openmmlab.platform.common.annotation.OnlyIntranetAccess)")
    public void onlyIntranetAccessOnClass() {}
    @Pointcut("@annotation(org.openmmlab.platform.common.annotation.OnlyIntranetAccess)")
    public void onlyIntranetAccessOnMethod() {}
    @Before(value = "onlyIntranetAccessOnMethod() || onlyIntranetAccessOnClass()")
    public void before() {
        HttpServletRequest hsr = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String from = hsr.getHeader("from");
        if (!StringUtils.isEmpty(from) && "public".equals(from)) {
            log.error("This api is only allowed invoked by intranet source");
            throw new MMException(ReturnEnum.C_NETWORK_INTERNET_ACCESS_NOT_ALLOWED_ERROR);
        }
    }
}

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OnlyIntranetAccess {}

Finally, annotate any API that should be internal‑only:

@GetMapping("/role/add")
@OnlyIntranetAccess
public String onlyIntranetAccess() {
    return "该接口只允许内部服务调用";
}

The article concludes with a reference to the original source and promotional links.

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.

MicroservicesaopBackend DevelopmentSpring CloudAPI Security
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

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.