Backend Development 12 min read

Building a Spring Cloud Gateway Service with Dynamic Routing via Nacos and Authentication Filter

This article demonstrates how to set up a Spring Cloud Gateway service using SpringBoot 2.1, configure static routes, implement dynamic routing through Nacos configuration listening, and create a custom authentication GlobalFilter, providing a step‑by‑step guide with Maven dependencies, YAML/JSON examples, and full Java code.

Top Architect
Top Architect
Top Architect
Building a Spring Cloud Gateway Service with Dynamic Routing via Nacos and Authentication Filter

The article explains how to build a gateway service with Spring Cloud Gateway, starting from the required Maven dependencies and the basic SpringBoot 2.1 parent configuration.

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.1.0.RELEASE</version>
</parent>

It adds the spring-cloud-gateway-core and commons-lang3 dependencies needed for routing and utility functions.

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-gateway-core</artifactId>
</dependency>

<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-lang3</artifactId>
</dependency>

Route Configuration

The static route is defined in application.yml (or application.yaml ) with fields such as id , uri , predicates , and filters . The example routes requests with path /demo-server/** to a backend service running at http://localhost:8081 and strips the first path segment.

server:
  port: 8080

spring:
  cloud:
    gateway:
      enabled: true
      routes:
        - id: demo-server
          uri: http://localhost:8081
          predicates:
            - Path=/demo-server/**
          filters:
            - StripPrefix=1

A table describes each configuration item (id, uri, predicates, filters) and their meanings.

Dynamic Routing with Nacos

To avoid restarting the gateway when routes change, the article shows how to store route definitions in Nacos. The Nacos dataId is routes and the content is a JSON array of RouteDefinition objects.

[
  {
    "id": "xxx-server",
    "order": 1,
    "predicates": [{"name": "Path", "args": {"pattern": "/xxx-server/**"}}],
    "filters": [{"name": "StripPrefix", "args": {"parts": 0}}],
    "uri": "http://localhost:8080/xxx-server"
  }
]

The JSON structure matches the YAML representation, making it easy to convert between the two formats.

Code Implementation for Dynamic Routing

A Spring component NacosDynamicRouteService implements ApplicationEventPublisherAware and listens to Nacos changes via @NacosConfigListener . When the configuration changes, it clears existing routes, parses the new JSON into RouteDefinition objects, saves them with RouteDefinitionWriter , and publishes a RefreshRoutesEvent to make the changes effective.

@Component
public class NacosDynamicRouteService implements ApplicationEventPublisherAware {
    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;
    private ApplicationEventPublisher applicationEventPublisher;
    private static List
routeIds = Lists.newArrayList();

    @NacosConfigListener(dataId = "routes", groupId = "gateway-server")
    public void routeConfigListener(String configInfo) {
        clearRoute();
        try {
            List
gatewayRouteDefinitions = JSON.parseArray(configInfo, RouteDefinition.class);
            for (RouteDefinition routeDefinition : gatewayRouteDefinitions) {
                addRoute(routeDefinition);
            }
            publish();
            LOGGER.info("Dynamic Routing Publish Success");
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
    }
    // clearRoute, addRoute, publish methods omitted for brevity
}

Custom Authentication Filter

The gateway can enforce authentication by implementing a GlobalFilter and Ordered . The filter extracts a token from the request header, query parameter, or cookie, validates it against Redis, refreshes its expiration, and adds a user_id header for downstream services.

@Component
public class AuthFilter implements GlobalFilter, Ordered {
    @Autowired
    private RedisTemplate
redisTemplate;
    private static final String TOKEN_HEADER_KEY = "auth_token";

    @Override
    public Mono
filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String token = getToken(request);
        ServerHttpResponse response = exchange.getResponse();
        if (StringUtils.isBlank(token)) {
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        String userId = getUserIdByToken(token);
        if (StringUtils.isBlank(userId)) {
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        request = exchange.getRequest().mutate().header("user_id", userId).build();
        resetTokenExpirationTime(token, userId);
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() { return 0; }

    private String getUserIdByToken(String token) {
        String redisKey = String.join(":", "auth_token", token);
        return redisTemplate.opsForValue().get(redisKey);
    }

    private void resetTokenExpirationTime(String token, String userId) {
        String redisKey = String.join(":", "auth_token", token);
        redisTemplate.opsForValue().set(redisKey, userId, 2, TimeUnit.HOURS);
    }

    private static String getToken(ServerHttpRequest request) {
        HttpHeaders headers = request.getHeaders();
        String token = headers.getFirst(TOKEN_HEADER_KEY);
        if (StringUtils.isBlank(token)) {
            token = request.getQueryParams().getFirst(TOKEN_HEADER_KEY);
        }
        if (StringUtils.isBlank(token)) {
            HttpCookie cookie = request.getCookies().getFirst(TOKEN_HEADER_KEY);
            if (cookie != null) token = cookie.getValue();
        }
        return token;
    }
}

Conclusion

The guide shows that Spring Cloud Gateway can be configured statically via YAML or dynamically via Nacos, and that custom filters such as authentication can be added easily by implementing the provided interfaces. The full code snippets and configuration examples enable readers to quickly set up a production‑ready gateway.

BackendJavaNacosDynamic RoutingSpring Cloud GatewayAuthentication Filter
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login 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.