spring boot中实现filter有三种常用方式:注解方式(@webfilter)、硬编码注册(filterregistrationbean)和配置类注册,执行顺序为filter→dispatcherservlet→interceptor→controller。

直接在网关 GlobalFilter 的 filter() 方法开头用 if-else 做快速拦截,关键不是写多深的嵌套,而是把最轻量、最高频、最危险的判断放在最前面——免签令牌(如固定 token、测试环境白名单 token、空 token)必须一眼识别、立即拒绝。
检查 Authorization Header 是否存在且非空
这是第一道防线。没带 token 或 token 为空,根本不用往下走。
- 若 header 不存在或值为空字符串,直接返回 401
- 注意区分
"Bearer "前缀后的实际值是否为空,避免只校验 header 键而忽略值
HttpHeaders headers = exchange.getRequest().getHeaders();
String auth = headers.getFirst("Authorization");
if (auth == null || auth.trim().isEmpty()) {
return errorResponse(exchange, 401, "missing_token");
}
识别免签类 token 模式并拦截
免签请求通常有明显特征:固定值(如 "test-token")、短字符串(dev/mock/debug)、或出现在生产环境的白名单 IP 之外。
- 提前配置免签黑名单(如
Set<string> bannedTokens = Set.of("test", "debug", "abc123")</string>) - 对 token 值做标准化截取(去掉
Bearer后取 base64 解码前的原始串)再比对 - 生产环境禁止
localhost、127.0.0.1、内网段 IP 直接携带免签 token 访问
String rawToken = auth.replaceFirst("Bearer\s+", "").trim();
if (bannedTokens.contains(rawToken) ||
rawToken.length() <p><strong>结合请求上下文做二次轻量验证</strong><br>
单靠 token 值不够,需叠加低开销上下文判断: </p>
- 请求路径是否属于敏感接口(如
/api/v1/user/delete)却用了免签 token - 请求 method 是 POST/PUT/DELETE 时,免签 token 默认不放行
- 查询参数含
?skip_auth=true但未通过 IP 白名单校验
String path = exchange.getRequest().getURI().getPath();
HttpMethod method = exchange.getRequest().getMethod();
if (isSensitivePath(path) && HttpMethod.POST.equals(method) && isBypassToken(rawToken)) {
return errorResponse(exchange, 403, "bypass_token_not_allowed_on_sensitive_endpoint");
}
避免常见性能陷阱
高并发下,每个判断必须 O(1),禁用正则、禁用远程调用、禁用 JSON 解析:
- 不解析 JWT payload,免签 token 本身就不该是合法 JWT
- 不查 Redis 或数据库,所有规则内置内存变量或 ConcurrentHashMap 缓存
- 所有字符串比较用
.equals()或.contains(),不用Pattern.compile() - 错误响应用预序列化 JSON 字节数组,避免每次 new String
不复杂但容易忽略。











