How to Restrict API Access to Internal Services Using Gateway and AOP
This article compares three approaches—microservice isolation, gateway with Redis whitelist, and a gateway‑plus‑AOP header strategy—to enforce internal‑only API access, and provides a complete Spring Cloud implementation with code examples and a diagram.
1. Separate Internal and External Interfaces with Microservices
Place external‑exposed APIs and internal‑only APIs in two different microservices. The internal service aggregates all APIs that should only be called within the intranet, but this adds an extra service, increases latency and maintenance cost.
2. Gateway + Redis Whitelist
Maintain a whitelist of API paths in Redis. When a request reaches the gateway, the gateway checks the whitelist; if the path is listed, the request is allowed, otherwise it is rejected. This approach requires no code changes but needs continuous whitelist management and adds a check on every request, which can degrade performance.
3. Gateway + AOP (Header‑Based Tagging)
Because external requests always pass through the gateway while internal service‑to‑service calls use Kubernetes service routing, the gateway can add a custom header (e.g., from=public) to external requests. In the business service, an AOP interceptor reads the header; if the header is present, the request is treated as external and blocked for APIs annotated with @OnlyIntranetAccess. This distributes the access‑control logic to each service, reduces gateway load, and improves response time, while the impact on business code can be minimized with annotations.
Implementation steps for the AOP solution:
@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; }
} @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("onlyIntranetAccessOnMethod() || onlyIntranetAccessOnClass()")
public void before() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String from = request.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 {} @GetMapping("/role/add")
@OnlyIntranetAccess
public String onlyIntranetAccess() {
return "该接口只允许内部服务调用";
}Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
