Implementing Internal‑Only APIs in Spring Cloud: Microservice Isolation, Gateway Whitelist, and AOP Approaches

This article explains three practical solutions for exposing internal‑only APIs in a Spring Cloud environment—separating services, using a gateway with a Redis whitelist, and applying a gateway‑plus‑AOP strategy—complete with code examples and deployment tips.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Implementing Internal‑Only APIs in Spring Cloud: Microservice Isolation, Gateway Whitelist, and AOP Approaches

Hello everyone, I'm Chen. When developing business services we often need an interface that should not be exposed externally and can only be called between internal services. This article explores feasible solutions and demonstrates one of them in detail.

1. Microservice Isolation for Internal and External APIs

Place externally exposed interfaces and internally‑only interfaces in two separate microservices: one service exposes all its APIs to the outside, while the other aggregates only the internal APIs for intra‑network calls.

This approach requires an additional microservice that aggregates internal‑only business interfaces, increasing system complexity, request latency, and maintenance cost.

2. Gateway + Redis Whitelist Mechanism

Maintain a whitelist of allowed interfaces in Redis; when a request reaches the gateway, the gateway checks Redis and forwards the request only if the interface is on the whitelist.

The advantage is zero intrusion to business code—just maintain the whitelist. The drawback is the continuous effort required to manage the whitelist, which often involves ticket submissions, and the added latency of per‑request checks, making the cost‑benefit ratio low.

3. Gateway + AOP Approach

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

External requests always pass through the gateway, while internal service‑to‑service calls use Kubernetes services directly. 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 AOP solution distributes access‑control logic across business services, eliminating a gateway bottleneck and improving code readability, though it introduces some code intrusion that can be mitigated with annotations.

Practical Implementation

Below is a concrete code demonstration of the AOP approach.

First, add the external‑network identifier header on the gateway side:

@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 control:

@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 "该接口只允许内部服务调用";
}

Final Note (Please Support)

All of my articles are carefully prepared. I have compiled three columns into PDFs, which can be obtained by following the public account "Code Monkey Technical Column" and replying with the corresponding keywords (e.g., "Spring Cloud Advanced"). If this article helped you, please like, view, share, and bookmark—it fuels my continued writing.

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 DevelopmentgatewaySpring Cloud
Code Ape Tech Column
Written by

Code Ape Tech Column

Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn

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.