读完这篇,你能做什么
能明确网关与业务服务各自的安全职责,并验证绕过网关时仍有资源保护。
学习理由、准备要求与知识点
为什么学它
网关验证身份并不能替代服务内部的资源授权,旁路入口和伪造请求头必须纳入设计。
先读这些内容
知识点清单
- 路由过滤器
- JWT 校验
- issuer 与 audience
TokenRelay- 身份请求头
- 服务侧授权
- 旁路入口
- 最小暴露
运行前先确认以 Gateway Server WebFlux 4.3.x 与 Spring Security 6.5 为学习主线,源码固定 6.5.0。Server MVC 使用不同过滤器模型。Java 17 算法只计算已验证身份的角色权限,不实现 JWT 密码学验证或资源归属校验。
01先弄懂它是什么
网关把外部请求集中接进来,可以分发请求、检查身份、做粗略权限控制和限制流量,但通常不知道每笔订单属于谁。认证回答调用者是谁,授权回答他能不能操作这条资源。用户登录成功,仍可能无权改别人订单;网关核验通过以后,下游还要按对象、租户和状态检查业务权限。
JWT 能解码出内容,不代表内容可信。要按允许的算法和可信密钥验证签名,再检查发行方、有效时间及应用要求的接收方,还要明确令牌用途和权限怎样对应。其他系统签发的有效 JWT,也不应随意用于当前服务。令牌核验应交给成熟安全组件,不能拿 Base64 解码代替认证。
身份传播也有信任边界。客户端自己带来的 X-User-Id 不是证据,网关若添加内部身份信息,必须先清理伪造输入并通过受保护链路传递,下游要验证调用来源或重新验证令牌。TokenRelay 的职责是转发适用的访问令牌,不会自动给令牌扩大受众或给用户授予订单权限。直接绕过网关的入口同样需要纳入部署与授权设计。
文中这几个词,先认一认
- 认证 Authentication
- 根据有效凭据建立可信身份,确认这次请求代表谁。
- 授权 Authorization
- 结合可信身份、目标资源、请求动作和规则,判断这一次操作是否允许。
- Reactor Context
- 在响应式调用过程中传递关联信息的机制,适合请求可能切换线程的情况。
- TokenRelay
- 把适用的 OAuth2 访问令牌转发给下游,不会自动增加权限、扩大接收范围或完成令牌交换。
02看看它怎么工作
这里有两层过滤流程。Spring Security 通过 WebFlux 的 WebFilter 处理身份认证和访问权限;Gateway 匹配到路由后,才把全局过滤器 GlobalFilter 与该路由的 GatewayFilter 组合起来。
后一条链中,请求进入时按优先顺序执行,响应返回时再反向经过对应的后续逻辑。理解顺序时,要先问自己正在看哪一层,再看排序值。不能因为某个 GlobalFilter 的顺序很靠前,就认为它会在所有请求的所有安全检查之前运行。
响应式代码描述的是订阅后执行的流水线。读取数据库、调用远端鉴权或读取大文件若直接阻塞事件循环,会拖慢共享线程上的其它连接。确需接入阻塞边界时,应采用受控执行器、并发上限和超时,并理解切换线程后普通 ThreadLocal 可能不再代表当前请求。认证信息应沿受支持的安全上下文传播,而不是在某线程存一个用户对象后期待它永远有效。
对订单修改可分两道判断:网关检查访问令牌和 orders:write 之类的能力,下游结合可信 userId、tenantId、订单 ownerId 与订单状态作最终授权。数据查询应在数据库条件中限定租户和归属,避免先返回整条敏感对象再在前端隐藏。批量操作要逐项或用统一约束核对全部对象,不能只验证列表第一项就放行整批。
正在加载流程图…
查看流程图源码(Mermaid)
flowchart TD
R["外部请求与不可信请求头"] --> A["安全链验证令牌"]
A --> V["签名、发行方、时间、受众与用途"]
V --> G["请求级权限判断"]
G --> C["清理伪造内部身份头"]
C --> P["按受保护身份传播契约转发"]
P --> D["下游验证凭据或可信调用来源"]
D --> O["租户、资源归属、业务状态授权"]
O --> B["执行条件更新"]
A --> X["认证失败响应"]
O --> Y["授权失败响应"]按顺序看,每一步做了什么
- 定义可信发行方、受众、算法和权限映射契约。
- 安全链验证凭据,按路由判断所需粗粒度能力。
- 去除外部伪造的内部身份头,按可信链路转发。
- 下游从可信上下文读取身份并限定资源查询范围。
- 业务更新再次使用条件约束,记录脱敏后的授权结果与关联 ID。
03对照实现代码
Spring Security 6.5.0 · AuthorizationWebFilter#filter
原创同步 Java 教学模型,仅映射“取得可信身份、执行策略、成功后继续链路”的关系。真实源码使用 Reactor Context、Mono 与 ReactiveAuthorizationManager.verify;模型不执行真实认证。
import java.util.*;
import java.util.function.*;
final class AuthorizationFlowModel {
record Principal(String user, Set<String> authorities) {}
static void protectedRoute(Optional<Principal> authenticated,
Predicate<Principal> policy, Runnable next) {
Principal principal = authenticated.orElseThrow(
() -> new SecurityException("authentication required")); // 受保护路由缺身份拒绝。
if (!policy.test(principal))
throw new SecurityException("access denied"); // 有身份仍需策略同意。
next.run(); // 只在前两关通过后进入后续链路。
}
}这段实现先从 ReactiveSecurityContextHolder 取出 Authentication,再交给 authorizationManager.verify,结合当前 ServerWebExchange 判断是否允许请求继续。这里不负责执行 JWT 签名算法,也不会自动理解全部业务角色规则。要查清身份为什么可信、权限具体怎么判断,需要继续看前面的认证组件和配置的授权管理器。
verify 返回 Mono<Void>,用“正常完成”表示校验通过,用“出错”表示失败,不需要再返回一个业务值。因此,没有值但正常完成,并不等于没有作出授权判断。AccessDeniedException 会沿错误处理路径继续传递,日志只是记录结果,不能代替判断。读 switchIfEmpty 时,要看它作用于链条中的哪一步,分清没有元素、正常完成和报错各自代表什么。
普通 ThreadLocal 依赖线程,而响应式请求可能在不同线程继续。真实实现使用响应式安全上下文,说明身份应与订阅链条关联,不能仅靠某个线程曾经处理过这个用户。自定义过滤器若跨执行器或自行 subscribe,可能丢失上下文或脱离正常响应生命周期,既影响授权也影响错误处理。
模型将缺少身份固定为拒绝,是针对受保护路由的教学约定。实际公开端点、匿名身份与多条安全链要通过明确配置表达,并对匹配顺序做测试。不能把模型直接复制为“所有路径都一样”的框架替代物;源码理解的重点是验证由哪个策略作裁决、失败是否阻止后续执行,以及资源级规则是否在正确层出现。
代码先调用谁,再调用谁
- 认证链验证凭据并建立响应式安全上下文
AuthorizationWebFilter取得 Authentication 流ReactiveAuthorizationManager.verify结合当前请求判断- 拒绝结果进入安全异常处理;成功完成后继续
WebFilterChain - Gateway 转发,下游继续执行资源与业务状态授权
04动手写一个例子
角色继承图上的权限闭包与显式拒绝
给定用户已验证角色集合、角色继承有向图及各角色权限集合,计算继承后的有效权限,再移除显式拒绝集合。继承图允许错误配置的环,算法必须终止;未知角色默认不产生权限。结果按权限名排序。
- 输入 1
admin继承editor,editor继承reader;权限依次delete,write,read;拒绝delete- 输出 1
[read,write]
- 输入 2
a继承b,b继承a;a有read- 输出 2
[read],遍历终止
角色继承是一个有向可达性问题。用户具有 admin,就需要检查从 admin 沿父角色边可以到达的全部角色,再收集它们的权限。使用队列做广度优先遍历,visited 记录已经处理过的角色;没有这个集合,配置中的环会造成无限遍历,多条路径到同一角色也会重复收集。
先合并允许权限,再统一移除显式拒绝,定义拒绝优先的规则。这样无论某个权限被多少个角色授予,只要它在拒绝集合中就不能出现在结果里。真实权限系统可能采用不同策略组合语义,所以必须在接口契约中固定规则,不能让遍历顺序决定“最后遇到允许还是拒绝”。
角色闭包只计算粗粒度能力,不包含订单归属。得到 orders:write 后,仍应在具体订单请求中判断租户、owner、状态等属性。用一个返回 Set 的算法替代全部授权,会把“允许操作某类资源”错误扩大为“允许操作任意实例”。算法测试因此专门包含未知角色与空身份,确保没有配置就不会凭空获得能力。
为什么这样写是对的visited 中每个角色都是从用户初始角色可达的;每个角色最多展开一次。输出是所有可达角色权限的并集减去显式拒绝集合。
V、E 是可达角色与继承边数,G 是这些角色的权限条目数,A 是移除显式拒绝前的唯一权限数,U 是最终有效权限数。visited 在出队时去重,每个角色只展开一次,但同一角色仍可被重复入队,队列峰值需要计入 O(E)。中间权限集合即使最终被全部拒绝也占 O(A)。散列集合通常均摊常数;输出排序为 O(U log U),长名称还要计入字符处理成本。
保存为 Main.java,运行 javac --release 17 -encoding UTF-8 Main.java,再运行 java Main。程序包含固定输入自测,断言失败时会抛出错误。
展开收起代码 · Main.java · 完整可运行程序
长行可在代码区域内左右滚动,按 Tab 可把焦点移入代码区。
import java.util.*;
public class Main {
static List<String> effective(Set<String> initial,
Map<String, Set<String>> parents, Map<String, Set<String>> grants,
Set<String> denied) {
Objects.requireNonNull(initial); Objects.requireNonNull(parents);
Objects.requireNonNull(grants); Objects.requireNonNull(denied);
ArrayDeque<String> queue = new ArrayDeque<>(initial);
Set<String> visited = new HashSet<>(), permissions = new HashSet<>();
while (!queue.isEmpty()) {
String role = queue.remove();
if (!visited.add(role)) continue; // 环与菱形继承都只处理一次。
permissions.addAll(grants.getOrDefault(role, Set.of()));
queue.addAll(parents.getOrDefault(role, Set.of())); // 沿继承边继续。
}
permissions.removeAll(denied); // 明确拒绝优先,不依赖角色遍历顺序。
List<String> result = new ArrayList<>(permissions);
Collections.sort(result);
return List.copyOf(result); // 不允许调用者改写已计算的权限快照。
}
static void eq(Object expected, Object actual) {
if (!Objects.equals(expected, actual)) throw new AssertionError(actual);
}
public static void main(String[] args) {
var parents = Map.of("admin",Set.of("editor"),"editor",Set.of("reader"));
var grants = Map.of("admin",Set.of("delete"),"editor",Set.of("write"),
"reader",Set.of("read"));
eq(List.of("read","write"), effective(Set.of("admin"),parents,grants,Set.of("delete")));
eq(List.of("read"), effective(Set.of("reader"),parents,grants,Set.of()));
eq(List.of(), effective(Set.of("unknown"),parents,grants,Set.of()));
eq(List.of(), effective(Set.of(),parents,grants,Set.of()));
eq(List.of("read"), effective(Set.of("a"),
Map.of("a",Set.of("b"),"b",Set.of("a")),Map.of("a",Set.of("read")),Set.of()));
eq(List.of(), effective(Set.of("reader"),parents,grants,Set.of("read")));
System.out.println("PASS 6");
}
}这些特殊情况也要试一试
- 继承图有环时必须终止,生产配置还应报告环作为治理问题。
- 未知角色不自动映射成管理员或默认高权限。
- 显式拒绝覆盖来自多条继承路径的允许。
- 权限快照不包含资源归属,也不替代令牌验证。
进阶选读 · 权限撤销、缓存版本与属性访问控制
场景用户离职后权限应尽快撤销,但网关与下游都缓存了角色闭包,令牌又仍未到期。
做法为策略与用户授权记录版本,缓存键包含租户、主体和策略版本;通过失效通知与有界 TTL 控制陈旧窗口。高风险操作读取权威状态或校验撤销版本,再结合资源属性作 ABAC 判断。策略更新采用不可变快照,避免一次请求混用新旧规则。
复杂度缓存命中可近似常数读取,但撤销传播、权威查询和角色闭包重算仍有成本;任意属性策略的复杂度取决于表达式与数据访问,不能一概称为 O(1)。
好处与代价更短陈旧窗口增加权威服务依赖和延迟;更长缓存提高可用性却延迟撤销。应按操作风险明确允许窗口与故障时拒绝或降级策略。
05项目里怎么用
网关把什么交给下游、下游相信哪些信息,需要提前约定。下游若接收原访问令牌,应检查令牌是否发给自己使用,以及权限是否够用;若使用内部服务凭据,则要验证调用服务的身份,并保证传来的用户信息没有被篡改、没有超出允许范围。转发令牌不会自动变成令牌交换,也不会增加权限。管理和调试入口同样要做授权检查,不能仅凭地址在内网就信任来访请求。
JWT 验证应使用成熟组件并固定可信配置,及时处理密钥轮换、时钟偏差和未知 key id。受众校验往往需要应用显式配置,不能假定默认签名校验已经覆盖所有业务声明。日志记录授权结果、拒绝原因类别和关联 ID 即可,避免打印完整令牌、密码或敏感请求体。错误响应也不应泄漏其它租户资源的详细存在性。
验收用多类请求覆盖边界:无令牌、过期令牌、错误发行方或受众、权限不足、伪造内部身份头、合法身份访问他人资源,以及批量列表中的混合归属。每次同时核对响应与数据库是否无副作用。测试环境中从下游直连入口发起同类请求,验证部署边界与应用授权都符合设计,不能只测浏览器隐藏了哪些按钮。
容易踩的坑
- 仅解码 JWT 就信任里面的用户与角色。
- 未清理客户端提供的内部身份头。
- 有路由级权限就允许任意订单或任意租户。
- 在
WebFlux事件循环中直接执行阻塞鉴权查询。 - 把
TokenRelay当成自动受众转换或资源授权。
几种做法,怎么选
表格有四列,窄屏可左右滑动查看代价和适用条件。
| 方案 | 优势 | 代价与限制 | 适用条件 |
|---|---|---|---|
| 网关集中认证,下游资源授权 | 统一入口策略,业务规则留在掌握数据的一层。 | 需要清晰身份传播契约与下游保护。 | 多数服务化系统的职责分层。 |
| 每个下游独立验证访问令牌 | 降低对单个入口信任的依赖。 | 重复验证与密钥、策略配置成本。 | 存在多入口或较强服务边界要求。 |
| 内部凭据加受保护用户上下文 | 可限制服务间调用范围。 | 签发、轮换、审计与上下文防篡改复杂。 | 有成熟服务身份基础设施。 |
| 集中在线授权查询 | 撤销与策略更新更及时。 | 增加延迟和依赖,需要有界缓存与故障策略。 | 高风险操作或动态属性规则较多。 |
06检验是否读懂了
先自己想、自己写,再展开答案核对。场景题是假设的练习情境;遇到还没学过的内容,可以做完基础后再回来。
先用自己的话解释
01验证 JWT 签名后为何仍要检查受众?
展开参考答案与推导
同一发行方可能给多个应用签发令牌,签名可信不代表当前服务就是允许接收和使用它的对象。
02角色图遍历为何必须 visited?
展开参考答案与推导
防止环无限循环和菱形继承重复展开,保证每个可达角色只处理一次。
03TokenRelay 能否代替订单归属检查?
展开参考答案与推导
不能。转发的是凭据,是否允许操作当前订单仍需结合可信身份与数据库业务属性。
换个情况,还会处理吗
01外部传 X-User-Id=管理员,系统该如何处理?
展开参考答案与推导
不能直接信任,应在入口移除或覆盖不可信内部头,下游只接受经过验证的身份契约,并以授权测试证明无越权副作用。
02网关 CPU 不高却所有请求延迟上涨,可能与鉴权有关吗?
展开参考答案与推导
可能事件循环被阻塞数据库或网络等待占住;检查线程与调用耗时,将必要阻塞工作放到受控边界并限制并发。
03用户角色已撤销,旧令牌仍能访问,怎样定位?
展开参考答案与推导
核对令牌有效期、角色来源、授权缓存及策略版本,按风险定义撤销窗口并验证失效传播,不能只改前端菜单。
写代码试一试
01增加菱形继承的去重测试。
- 输入 / 条件
admin继承a,b,a与b都继承reader;reader有read- 输出 / 预期
[read]
提示 同一角色可能从多条路径到达。
展开参考答案与推导
验证 visited 使 reader 只展开一次,输出 Set 防止权限重复,加入显式deny后结果为空。
02给访问订单函数加入租户与归属条件。
- 输入 / 条件
用户tenantA/u1,订单tenantB/u1- 输出 / 预期
拒绝
提示 用户名相同不表示同租户。
展开参考答案与推导
查询同时限定 tenantId 与 ownerId,只有可信上下文提供这两项,批量请求全部对象都必须满足。
03为授权快照增加版本键。
- 输入 / 条件
同用户策略v1允许write,v2撤销write- 输出 / 预期
v2请求不得复用v1结果
提示 缓存键要包含策略版本。
展开参考答案与推导
构造不可变缓存键(tenant,user,version),切换策略后用新版本查找并重算;同时设计旧缓存清理和撤销通知。
读完之后,独立完成
课后作业:自己做一遍
本篇共 12 道作业,先完成 9 道基础与综合任务,再按前置知识挑战进阶题。其中包含 2 道思维拓展,试着换个条件,看看原来的办法是否还管用。不附参考答案。
能明确网关与业务服务各自的安全职责,并验证绕过网关时仍有资源保护。
本篇重点加练
令牌的信任范围和资源级授权必须分开验证,跨入口或跨租户时尤其容易混淆。
- issuer 与 audience
- 服务侧授权
重点内容会多练几次。先说清楚怎么做,再试试空数据、出错或条件改变时会发生什么。
先自己做,卡住时记下问题,再回来查。问答题写清“为什么、什么时候适用”;动手题留下输入、输出和运行步骤,方便下次重做。
基础必做
- 作业 01代码推演
同一路由依次有路径改写、令牌解析和鉴权过滤器。构造一个不存在令牌及一个损坏令牌的请求,标明在哪一步生成响应以及下游是否会执行。
- 提交内容
- 过滤器时序与请求记录
- 怎样算完成
- 注明过滤器顺序
- 覆盖异常和正常短路
练到的知识点路由过滤器 · JWT 校验
- 作业 02原理问答
公司有管理端与开放 API 两类受众,用户令牌来自同一发行方。评审把管理端令牌直接转发到开放服务的约定。
- 提交内容
- 令牌声明与信任关系表
- 怎样算完成
- 区分 issuer、audience 和转发行为
- 说明服务对令牌的预期
练到的知识点issuer 与 audience · TokenRelay
- 作业 03原理问答
一个发行者给移动端与批处理任务签发令牌,二者权限名称相同但用途不同。建立受众、客户端和主体三种身份的区分。
- 提交内容
- 声明与信任关系图
- 怎样算完成
- 不把权限字符串当作受众
- 注明多受众令牌的业务约定
练到的知识点issuer 与 audience
综合应用
- 作业 04面试场景
请求经过公网网关和内部代理,两处都可能添加身份头。为订单读取制定身份来源优先规则及对象授权证据。
- 提交内容
- 请求头契约与授权矩阵
- 怎样算完成
- 包含同名头的重复值
- 检查服务侧租户和对象归属
练到的知识点身份请求头 · 服务侧授权
- 作业 05设计评审
部署后开发端口仍能直接访问业务服务。列出网关、业务服务与管理入口应暴露的功能,并设计本地入口审查。
- 提交内容
- 网络入口图与检查表
- 怎样算完成
- 包含健康和管理端点
- 区分网络限制与业务授权
练到的知识点旁路入口 · 最小暴露
- 作业 06编程实践
搭建仅回环可访问的网关与桩服务,用测试令牌和伪造身份头执行一组正反请求,记录每一层实际接收的身份信息。
- 提交内容
- 本地工程与请求日志
- 怎样算完成
- 不得使用真实生产令牌
- 覆盖网关路径和受控直连路径
练到的知识点路由过滤器 · JWT 校验 · issuer 与 audience · 身份请求头 · 服务侧授权 · 旁路入口
- 作业 07代码推演
批量订单查询包含当前用户和另一用户的订单 ID,产品允许返回部分结果。设计逐项授权与整体失败两种契约的可观察差异。
- 提交内容
- 批量授权矩阵
- 怎样算完成
- 包含重复 ID 和不存在对象
- 说明数量是否泄露额外信息
练到的知识点服务侧授权
- 作业 08面试场景
内部服务收到为网关签发的令牌,调用链里另带“代表用户执行”标识。评审实际主体、委托主体与订单授权证据。
- 提交内容
- 委托调用身份表
- 怎样算完成
- 区分服务身份和用户权限
- 不凭可伪造头声明委托成立
练到的知识点issuer 与 audience · 服务侧授权
- 作业 09编程实践
用本地测试密钥和授权桩生成令牌声明组合,自动运行发行方、受众、租户及对象权限矩阵,输出实际决策与决策来源。
- 提交内容
- 本地工程与矩阵报告
- 怎样算完成
- 只使用虚构身份及密钥
- 分别核验令牌校验和资源授权
练到的知识点issuer 与 audience · 服务侧授权
进阶挑战 · 掌握前置后选做
- 作业 10设计评审
引入第二个身份提供者,两个提供者都可能签发相同 sub。审查账户映射、令牌转发和最小权限策略,设计迁移期测试。
- 提交内容
- 信任模型与冲突用例
- 怎样算完成
- 区分全局账户与发行方主体
- 包含未知发行方和受众不符
练到的知识点JWT 校验 · issuer 与 audience · TokenRelay · 服务侧授权 · 最小暴露
思维拓展
先写出你的猜想,再用例子或实验验证。答案可以不同,但要说清依据、适用情况,以及还有什么没弄懂。
- 作业 11思维拓展 · 反例构造
构造“签名、过期时间和角色检查全部通过,业务访问仍越权”的两个反例,要求两例的缺陷不属于同一控制点。
- 提交内容
- 反例请求及缺失检查
- 怎样算完成
- 每例说明已通过的检查
- 不靠伪造签名绕过前提
练到的知识点issuer 与 audience · 服务侧授权
- 作业 12思维拓展 · 跨域迁移
将网关信任模型迁移到 AI Agent 代用户调用工具,Agent 可持有长期服务凭据。重新定义工具目标受众、委托范围及每次调用的授权依据。
- 提交内容
- 工具调用信任图
- 怎样算完成
- 区分模型建议与可信身份
- 覆盖多用户同时委托
练到的知识点issuer 与 audience · 服务侧授权
完成后,再检验一次
给每题标记“独立完成 / 查阅后完成 / 尚未完成”。查过资料或没做出的题,记下卡在哪里。隔一天换一组输入再试,能解释结果和出错原因,再把这个知识点标为掌握。
继续阅读
先看能帮你完成当前练习的部分。例子跑通后,再读更深入的解释。
- 必读参考文档英文
Spring Cloud Gateway:TokenRelay (新标签页)↗
阅读令牌转发前提与过滤器行为,区分传递令牌和资源授权。
- 实践参考文档英文
Spring Security:JWT Resource Server (新标签页)↗
阅读签名、issuer 和受众校验,明确 JWT 验证的条件与扩展点。
- 深入实践指南英文
OWASP:Authorization Cheat Sheet (新标签页)↗
阅读默认拒绝、每次请求校验和对象权限,建立权限矩阵及反例测试。
- 深入参考文档英文
Spring Security:Authorize HTTP Requests (新标签页)↗
阅读请求匹配与授权规则,明确公共入口及受保护资源。
- 实践实践指南英文
Bucket4j:把限流速度与突发容量分开看 (新标签页)↗
先读初始令牌和 Refill styles,暂跳 Servlet、阻塞等待、集群后端和动态换配置。在纸上把建桶时记为 0 毫秒:容量 3、初始 3、每秒补 2 个,每次请求尝试取 1 个;取不到就立即拒绝,不等待。按列表顺序处理 0、0、0、0、250、500、1000 毫秒的请求,同一时刻的四个请求也依次处理。分别画逐步补充和整批补充的表;整批补充从建桶满一秒时开始,先补足该时刻按规则应得的额度,再处理请求,最多不超过容量。 参考文档公开可读。所选页面的 core 依赖示例面向 JDK 17;练习单进程内存桶无需 Redis。多个进程各建一个桶不会自动共享总额度。
- 深入参考文档英文
Gateway 4.3:TokenRelay (新标签页)↗
阅读访问令牌转发前置配置及默认授权客户端存储限制。
- 深入参考文档英文
Spring Security 6.5:响应式 JWT (新标签页)↗
核对签名、发行方、时间、受众与权限映射。
- 深入参考文档英文
AuthorizationWebFilter 6.5.0 源码 (新标签页)↗
对照 Reactor 安全上下文、verify 与错误传播。
- 深入参考文档英文
Gateway 4.3:Global Filters (新标签页)↗
理解过滤器组合、排序与前后置执行。
- 深入参考文档英文
RFC 8725:JWT 最佳实践 (新标签页)↗
阅读算法验证、发行方与受众约束及令牌用途隔离。