Implementing Internal‑Only APIs with Gateway and AOP in a Microservice System

This article explains how to restrict certain microservice interfaces to internal calls only by using two approaches—gateway with whitelist and gateway combined with AOP—detailing the implementation steps, code examples, and trade‑offs in a Spring Cloud environment.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Implementing Internal‑Only APIs with Gateway and AOP in a Microservice System

When a service needs an interface that should not be exposed externally, developers can choose between two common solutions: a gateway with a whitelist or a gateway combined with AOP. The whitelist approach stores allowed endpoints in a cache and lets the gateway filter requests, but it requires ongoing maintenance and adds latency.

The gateway + AOP method moves the source‑checking logic to the business side, improving response time. By adding a custom header (e.g., from=Y) to internal requests, the gateway can strip the header for security, and an AOP aspect validates the header before the controller method executes.

Implementation Steps

1. Define an annotation to mark internal‑only endpoints:

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Inner {
    /**
     * Whether AOP should handle this annotation
     */
    boolean value() default true;
}

2. Gateway filter that removes the from header and records request start time:

/**
 * {@link com.code.ape.codeape.gateway.filter.CodeapeRequestGlobalFilter#filter}
 * @author 公众号:码猿技术专栏
 * @url: www.java-family.cn
 */
public class CodeapeRequestGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1. Clean the "from" header
        ServerHttpRequest request = exchange.getRequest().mutate().headers(httpHeaders -> {
            httpHeaders.remove(SecurityConstants.FROM);
            // Set request start time
            httpHeaders.put(CommonConstants.REQUEST_START_TIME,
                Collections.singletonList(String.valueOf(System.currentTimeMillis())));
        }).build();
        // ... further processing ...
    }
}

3. Feign client that automatically adds the header for internal calls:

@FeignClient(contextId = "remoteDeviceService", value = ServiceNameConstants.DEVICE_SERVICE)
public interface RemoteDeviceService {

    /**
     * Query device by SN
     */
    @GetMapping(value = "/device/sn/{sn}", headers = "from=Y")
    R<DeviceInfoVO> getBySn(@PathVariable("sn") String sn);
}

4. AOP aspect that checks the from header and throws AccessDeniedException if the request is not internal:

// com.code.ape.codeape.common.security.component.CodeapeSecurityInnerAspect
@Slf4j
@Aspect
@RequiredArgsConstructor
public class CodeapeSecurityInnerAspect implements Ordered {

    private final HttpServletRequest request;

    @SneakyThrows
    @Around("@within(inner) || @annotation(inner)")
    public Object around(ProceedingJoinPoint point, Inner inner) {
        // Retrieve the "from" header
        String header = request.getHeader("from");
        // Verify header value
        if (inner.value() && !"Y".equals(header)) {
            log.warn("Access to method {} is denied", point.getSignature().getName());
            throw new AccessDeniedException("Access is denied");
        }
        return point.proceed();
    }
    // ... other methods ...
}

When the header check fails, the aspect throws an exception that is caught globally and results in a 403 response.

Summary

The article presented two ways to keep certain microservice APIs internal: a gateway + whitelist and a gateway + AOP solution. The latter reduces gateway load by delegating the check to the service layer, uses a custom @Inner annotation, and integrates seamlessly with Feign clients via the from=Y header.

Choosing the appropriate method depends on project requirements, maintenance overhead, and performance considerations.

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.

JavaMicroservicesaopfeigngatewaySpring CloudInternal API
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.