Securing Spring Cloud Gateway Requests with Token Filters and Feign Header Interceptor

This article demonstrates how to secure microservice communication by adding a request token in Spring Cloud Gateway, implementing a global filter to validate the token, and configuring a Feign interceptor to automatically attach the required header, ensuring all services route through the gateway.

Top Architect
Top Architect
Top Architect
Securing Spring Cloud Gateway Requests with Token Filters and Feign Header Interceptor

In a microservice architecture, the gateway is a critical entry point where various filters can be added to validate request parameters, enforce rate limiting, and ensure security. Bypassing the gateway would allow direct access to internal services, so protecting the gateway is essential.

Idea

Add a request token to every request passing through the gateway.

In each downstream service, add a filter that validates the token.

First, create a global filter in the gateway service that injects a custom header (e.g., "from": "gateway") into every outgoing request.

package com.hpsyche.hpsychegatewayserver.filter;

import com.hpsyche.hpsychegatewayserver.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @author Hpsyche
 */
public class TokenFilter implements GlobalFilter {
    @Autowired
    private RedisUtil redisUtil;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // token (user identity) validation
        // ...
        ServerHttpRequest req = exchange.getRequest().mutate()
                .header("from", "gateway")
                .build();
        return chain.filter(exchange.mutate().request(req.mutate().build()).build());
    }
}

If higher security is required, the header value can be a UUID stored in Redis and verified by downstream services.

Next, add a global interceptor in the authentication service to check the from header. If the header is missing or incorrect, the service returns an error response.

package com.hpsyche.hpsycheauthserver.interceptor;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

/**
 * @author Hpsyche
 */
@Slf4j
public class GlobalInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String secretKey = request.getHeader("from");
        if (!StringUtils.isNotBlank(secretKey) || secretKey.equals("gateway")) {
            response.setContentType("application/json; charset=utf-8");
            PrintWriter writer = response.getWriter();
            writer.write("error");
            return false;
        }
        return true;
    }
}

When a request bypasses the gateway and directly calls the auth service, the interceptor returns an error, confirming that the gateway is mandatory.

Problem

Feign remote calls failed because Feign does not go through the gateway, so the required from header is missing and the interceptor blocks the request.

Solution

Add a Feign request interceptor that automatically adds the from header, and configure the Feign client to use this interceptor.

package com.hpsyche.hpsycheauthclient.config;

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Configuration;

/**
 * Feign interceptor to add the "from" header
 */
@Configuration
public class FeignConfiguration implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        requestTemplate.header("from", "gateway");
    }
}

Also, specify the interceptor in the Feign client definition:

package com.hpsyche.hpsycheauthclient.api;

import com.hpsyche.hpsychecommonscommon.vo.BaseResponse;
import com.hpsyche.hpsycheauthclient.config.FeignConfiguration;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(value = "hpsyche-auth-server", configuration = FeignConfiguration.class)
public interface AuthService {
    @PostMapping("/auth/verifyUser")
    BaseResponse verifyUser(@RequestParam("username") String username,
                           @RequestParam("password") String password);
}

With this configuration, every Feign call automatically includes the required header, allowing the request to pass through the gateway and be accepted by the authentication service.

Conclusion

When building microservice systems, think carefully about security at the gateway level, add necessary request metadata, and ensure that all internal calls (including Feign) propagate this metadata. Leveraging Spring Cloud Gateway filters and Feign interceptors provides a clean, reusable solution.

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.

JavafeignSpring Cloud GatewayRequest HeaderToken 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

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.