EBEasyBuild Docs
文档/后端/网关

easyfk-gateway 网关模块

网关过滤层模块 — 统一流量入口与安全防护阅读时间 ~15 min

1. 模块概述

easyfk-gateway 是 EasyFK 框架的网关过滤层模块,基于 Spring Cloud Gateway 构建,提供全局请求过滤、安全签名校验、会话管理、权限拦截等核心网关能力。该模块作为所有请求的统一入口,实现了请求头解析、接口安全验证、登录态检测、权限控制等完整的网关过滤链。

TIP
easyfk-gateway 作为微服务架构的流量入口,所有外部请求均经由此模块进行安全校验和权限拦截后,再转发至下游服务。

2. 模块依赖

依赖模块依赖方式说明
easyfk-coreapi核心模块,提供 DTO、上下文、工具类等
easyfk-web:web-commonapiWeb 公共模块,提供拦截配置、安全属性、URI 工具等
easyfk-authorityapi权限模块,提供权限校验和资源安全级别判断
spring-cloud-starter-gatewayapiSpring Cloud Gateway 核心(排除 logging)
groovy
dependencies {
    api project(':easyfk-core')
    api project(':easyfk-web:web-common')
    api project(':easyfk-authority')
    api('org.springframework.cloud:spring-cloud-starter-gateway') {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
    }
}

3. 包结构

plaintext
com.mcst.easyfk.gateway
├── config/                   # 自动配置
│   └── GatewayFilterConfigure  - Spring Boot 自动配置类
├── filter/                   # 过滤器
│   ├── RequestGatewayFilter    - 核心全局网关过滤器
│   ├── ICustomGatewayFilter    - 自定义网关过滤器接口
│   └── IExtendGatewayFilter    - 扩展网关过滤器接口
└── util/                     # 工具类
    └── FailRequestUtil         - 失败响应工具类

4. 核心组件详解

4.1 RequestGatewayFilter —— 全局网关过滤器

RequestGatewayFilter 实现了 GlobalFilterOrdered 接口,是模块的核心类,处理所有经过网关的请求。

执行优先级:getOrder() = 0(最高优先级)

4.1.1 依赖注入

依赖类型注入方式说明
securityPropertiesSecurityProperties@Resource安全配置属性
gatewayPropertiesGatewayProperties@ResourceSpring Cloud Gateway 路由配置
propertiesInterceptProperties@Resource拦截器配置属性
cacheServiceICacheService@Resource @Lazy缓存服务(延迟加载)
userDataManagerUserDataManager@Autowired(required=false)用户权限管理器(可选)
interceptPropertiesInterceptProperties@Resource拦截器配置
customGatewayFilterICustomGatewayFilter@Autowired(required=false)自定义过滤器(可选)
authResourceApiIAuthResourceApi@Resource @Lazy权限资源 API(延迟加载)
contextDataManagerContextDataManager@Resource上下文数据管理器

4.1.2 过滤器主流程

plaintext
请求进入 filter()
    │
    ├─ 1. OPTIONS 请求 → 直接放行
    │
    ├─ 2. 自定义过滤器开关 → 委托 ICustomGatewayFilter 处理
    │
    ├─ 3. Knife4j 文档请求(/v3/api-docs)→ 路径重写后放行
    │
    ├─ 4. 解析请求头 → 构建 RequestHeaders 对象
    │     ├─ Reset-Sign(签名)
    │     ├─ Param-Sign(参数签名)
    │     ├─ Timestamp(时间戳)
    │     ├─ Request-Token(请求令牌)
    │     ├─ Access-Token(访问令牌)
    │     ├─ Request-Nonce(请求随机数)
    │     ├─ Device-No(设备号)
    │     └─ Client-Type(客户端类型)
    │
    ├─ 5. 创建 TraceId(链路追踪)
    │
    ├─ 6. 会话过滤(sessionFilter)→ 加载用户数据上下文
    │
    ├─ 7. 安全过滤(securityFilter,可开关)
    │     └─ 失败 → 清理上下文 + 返回错误响应
    │
    ├─ 8. 网关拦截(gatewayIntercept,可开关)
    │     ├─ 排除 URI → 直接放行
    │     ├─ LOGIN 级别 → 检查登录态
    │     └─ AUTHORITY 级别 → 检查登录态 + 权限
    │
    └─ 9. 返回成功 → 将 FilterChainData 写入请求头传递给下游服务
         └─ doFinally → 清理 ThreadLocal 上下文
  1. OPTIONS 预检请求直接放行,不进入后续过滤链
  2. 自定义过滤器开关启用时,委托 ICustomGatewayFilter 完全接管处理
  3. Knife4j 文档路径自动重写,确保网关层 API 文档聚合正常
  4. 请求头解析为 RequestHeaders 对象,统一上下文传递
  5. 每个请求生成唯一 TraceId,贯穿整个链路追踪
  6. 会话过滤加载用户数据到 ThreadLocal 上下文
  7. 安全签名校验可通过配置开关控制
  8. 网关拦截根据资源安全级别执行不同策略
  9. 过滤完成后,上下文数据写入请求头传递给下游服务

4.1.3 安全签名校验流程(securityFilter)

securityProperties.isOpen() == true 时启用:

plaintext
securityFilter(exchange)
    │
    ├─ 1. 检查是否在忽略 URI 列表中 → 是则直接通过
    │
    ├─ 2. 校验请求头必填项
    │     ├─ RequestHeaders 不能为空
    │     ├─ Request-Nonce 不能为空
    │     ├─ Reset-Sign 不能为空
    │     └─ Timestamp 不能为空
    │
    ├─ 3. 获取签名密钥
    │     ├─ 静态模式 → 使用配置的 signKey
    │     └─ 动态模式 → 从缓存获取动态密钥
    │
    ├─ 4. 签名验证
    │     拼接:Request-Nonce={nonce}&Timestamp={ts}&Key={key}
    │     计算:MD5(拼接字符串)
    │     比较:计算结果 vs 请求头中的 Reset-Sign
    │
    └─ 5. 防重放攻击
          ├─ 检查 Request-Nonce 是否已存在于缓存
          │   └─ 存在 → 拒绝(接口重复调用)
          └─ 不存在 → 缓存该 Nonce(设置超时时间)

签名算法:

plaintext
signText = "Request-Nonce=" + nonce + "&Timestamp=" + timestamp + "&Key=" + signKey
sign = MD5(signText)
注意
签名校验采用 MD5 算法,请确保 signKey 的安全性。动态模式下密钥从缓存获取,需保证缓存服务的可用性。

4.1.4 网关拦截流程(gatewayIntercept)

properties.isOpenGatewayInterceptor() == true 时启用:

plaintext
gatewayIntercept(exchange, chain, gatewayData)
    │
    ├─ 1. 排除 URI 检查 → 匹配则直接放行
    │
    ├─ 2. 解析服务名
    │     └─ 从 Gateway 路由配置中匹配请求 URI 对应的服务
    │
    ├─ 3. 获取资源安全级别
    │     └─ authResourceApi.checkUriSecurityLevel(requestUri)
    │
    ├─ 4. 根据安全级别判断
    │     ├─ UNIMPEDED → 直接通过
    │     ├─ LOGIN → 检查 UserData 是否存在
    │     │   └─ 不存在 → 返回未登录错误
    │     └─ AUTHORITY → 检查 UserData + 权限
    │         ├─ 未登录 → 返回未登录错误
    │         └─ 无权限 → 返回未授权错误
    │
    └─ 5. 通过 → 写入 FilterChainData 到下游请求头
TIP
资源安全级别分为三档:UNIMPEDED(完全放行)、LOGIN(需要登录)、AUTHORITY(需要登录 + 权限),由 IAuthResourceApi 动态判定。

4.1.5 请求头传递机制

过滤器通过后,FilterChainData(包含解析后的请求头信息)被序列化为 JSON,写入下游请求的 CHAIN_NAME Header 中:

java
ServerHttpRequest request = exchange.getRequest().mutate()
    .header(RequestHeaderConstant.CHAIN_NAME, JSON.toJSONString(gatewayData))
    .build();

下游微服务可通过该 Header 获取网关层解析后的统一上下文数据

4.2 ICustomGatewayFilter —— 自定义网关过滤器接口

当业务需要完全替换默认过滤逻辑时使用。

java
public interface ICustomGatewayFilter {
    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}

启用条件:配置 properties.isCustomGatewayFilter() == true,并注册 ICustomGatewayFilter 实现 Bean。

java
@Component
public class MyCustomGatewayFilter implements ICustomGatewayFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 完全自定义的过滤逻辑
        return chain.filter(exchange);
    }
}

4.3 IExtendGatewayFilter —— 扩展网关过滤器接口

当业务需要在默认过滤流程基础上追加扩展逻辑时使用。

java
public interface IExtendGatewayFilter {
    void doExtendIntercept(ServerWebExchange exchange);
}
java
@Component
public class MyExtendFilter implements IExtendGatewayFilter {

    @Override
    public void doExtendIntercept(ServerWebExchange exchange) {
        // 附加的拦截逻辑,如日志记录、限流等
    }
}

4.4 FailRequestUtil —— 失败响应工具类

提供统一的网关层错误响应构建能力:

java
public static Mono<Void> failRequest(ServerWebExchange exchange, ErrorRequest errorRequest)

响应格式:HTTP 状态码 400 Bad Request,Content-Type 为 application/json; charset=utf-8,响应体为 ResponseResult JSON 格式。

错误说明
HEARD_EMPTY请求头为空
NONCE_EMPTY随机数为空
RESET_SIGN_EMPTY签名为空
TIMESTAMP_EMPTY时间戳为空
DYNAMIC_SIGN_KEY_TIMEOUT动态签名密钥超时
SIGN_ERROR签名验证失败
API_AGAIN接口重复调用
UNLOGIN未登录
UNAUTH未授权

4.5 GatewayFilterConfigure —— 自动配置

java
@AutoConfiguration
public class GatewayFilterConfigure {

    @Bean
    @ConditionalOnMissingBean
    public RequestGatewayFilter requestHeaderGatewayFilter() {
        return new RequestGatewayFilter();
    }
}

通过 Spring Boot 自动配置注册 RequestGatewayFilter Bean。使用 @ConditionalOnMissingBean,支持业务覆盖默认实现。

5. 配置项说明

配置来源关键属性说明
SecurityPropertiesopen是否开启安全签名校验
signKey签名密钥
signKeyDynamic是否使用动态签名密钥
ignoreUri忽略安全校验的 URI 列表
timeoutNonce 缓存超时时间(防重放)
InterceptPropertiesopenGatewayInterceptor是否开启网关权限拦截
customGatewayFilter是否启用自定义过滤器
refreshUserAuth是否刷新用户权限缓存
排除 URI 配置不拦截的 URI 列表

6. 请求头常量

以下请求头将被网关解析并封装到 RequestHeaders 对象中:

Header 名称对应字段说明
Reset-SignresetSign请求签名
Param-SignparamSign参数签名
Timestamptimestamp请求时间戳
Request-TokenrequestToken请求令牌
Access-TokenaccessToken访问令牌
Request-NoncerequestNonce请求随机数(防重放)
Device-NodeviceNo设备编号
Client-TypeclientType客户端类型

7. 集成指南

7.1 引入依赖

groovy
dependencies {
    implementation project(':easyfk-gateway')
}

7.2 基本配置

yaml
# 开启安全签名校验
security:
  open: true
  sign-key: "your-sign-key"
  sign-key-dynamic: false
  timeout: 300

# 开启网关权限拦截
intercept:
  open-gateway-interceptor: true
  custom-gateway-filter: false
  refresh-user-auth: true

7.3 自定义过滤器

方式一:完全替换 —— 实现 ICustomGatewayFilter,开启 customGatewayFilter 配置。

方式二:扩展追加 —— 实现 IExtendGatewayFilter,在默认流程基础上追加逻辑。

方式三:替换核心过滤器 —— 注册自定义 RequestGatewayFilter Bean 覆盖默认实现。

TIP
三种自定义方式的优先级依次递增:扩展追加 < 完全替换 < 替换核心过滤器。推荐优先使用扩展追加方式,保留默认安全过滤链。

7.4 Knife4j 文档集成

模块内置了对 Knife4j API 文档的支持。当请求 URI 包含 /v3/api-docs 时,自动将路径重写为 /v3/api-docs,确保网关层的文档聚合正常工作。

easyfk-gateway — API 网关,为微服务提供统一的流量入口与安全防护。

— END —