You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

已有Zuul服务路由,如何通过Spring Cloud Gateway实现白名单域名过滤?

解决方案:域名白名单过滤实现

不管是Spring Cloud Gateway还是你当前使用的Zuul,都可以实现域名白名单过滤需求,以下是两种具体方案:

方案一:Spring Cloud Gateway 实现方式

你可以通过自定义GatewayFilterFactory来实现域名白名单校验,步骤如下:

1. 自定义网关过滤器工厂

创建一个过滤器工厂类,读取配置的白名单域名,校验请求的Origin或Referer头是否在白名单内:

import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import java.util.List;

@Component
public class DomainWhitelistGatewayFilterFactory extends AbstractGatewayFilterFactory<DomainWhitelistGatewayFilterFactory.Config> {

    public DomainWhitelistGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            // 获取请求头中的Origin或Referer
            String origin = exchange.getRequest().getHeaders().getFirst("Origin");
            String referer = exchange.getRequest().getHeaders().getFirst("Referer");
            String requestDomain = null;

            // 优先取Origin,没有则取Referer
            if (origin != null) {
                requestDomain = extractDomain(origin);
            } else if (referer != null) {
                requestDomain = extractDomain(referer);
            }

            // 校验域名是否在白名单内
            if (requestDomain == null || !config.getAllowedDomains().contains(requestDomain)) {
                exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
                return exchange.getResponse().setComplete();
            }

            return chain.filter(exchange);
        };
    }

    // 从URL中提取域名(去掉协议、端口、路径等)
    private String extractDomain(String url) {
        return url.replaceAll("^https?://(www\\.)?|(:\\d+).*$", "");
    }

    public static class Config {
        private List<String> allowedDomains;

        public List<String> getAllowedDomains() {
            return allowedDomains;
        }

        public void setAllowedDomains(List<String> allowedDomains) {
            this.allowedDomains = allowedDomains;
        }
    }
}

2. 配置路由与白名单

在application.yml中配置路由,并应用该过滤器,指定允许的域名:

spring:
  cloud:
    gateway:
      routes:
        - id: your-service-route
          uri: lb://your-service
          predicates:
            - Path=/api/**
          filters:
            - name: DomainWhitelist
              args:
                allowedDomains:
                  - example.com
                  - trusted-domain.com

方案二:现有Zuul 改造实现

如果你不想替换Zuul,可以通过自定义Zuul过滤器来实现相同逻辑:

1. 自定义Zuul过滤器

创建一个前置过滤器(pre类型),在请求路由前校验域名:

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

@Component
public class DomainWhitelistZuulFilter extends ZuulFilter {

    @Value("${zuul.domain.allowed-list}")
    private List<String> allowedDomains;

    @Override
    public String filterType() {
        return "pre"; // 前置过滤器,在路由前执行
    }

    @Override
    public int filterOrder() {
        return 1; // 执行顺序,数字越小越先执行
    }

    @Override
    public boolean shouldFilter() {
        return true; // 是否启用该过滤器
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();

        // 获取请求头中的Origin或Referer
        String origin = request.getHeader("Origin");
        String referer = request.getHeader("Referer");
        String requestDomain = null;

        if (origin != null) {
            requestDomain = extractDomain(origin);
        } else if (referer != null) {
            requestDomain = extractDomain(referer);
        }

        // 校验域名
        if (requestDomain == null || !allowedDomains.contains(requestDomain)) {
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(HttpStatus.FORBIDDEN.value());
            ctx.setResponseBody("Forbidden: Request domain is not allowed");
        }

        return null;
    }

    private String extractDomain(String url) {
        return url.replaceAll("^https?://(www\\.)?|(:\\d+).*$", "");
    }
}

2. 配置白名单

在application.yml中添加白名单配置:

zuul:
  domain:
    allowed-list: example.com,trusted-domain.com

注意事项

  • 可以根据业务需求调整域名提取逻辑,比如是否保留www前缀、是否需要匹配子域名等
  • 对于没有Origin和Referer头的请求(比如直接API调用),可以根据需求选择允许或拦截,可在过滤器中添加自定义逻辑处理
  • 白名单建议配置在配置中心,方便动态修改

内容的提问来源于stack exchange,提问作者Shivam Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 22:41:06