拦截器
拦截器概述
在基于 Tio-Boot 的 HTTP 应用中,拦截器(Interceptor)是一种在请求到达业务处理器之前或响应返回客户端之后,对请求/响应进行预处理和后处理的机制。合理地使用拦截器,可用于集中化地处理以下场景:
- 请求校验:验证 HTTP 请求是否合法,拦截恶意或缺少关键信息的请求
- 鉴权与权限控制:检查请求的认证信息或用户权限
- 日志记录:统一记录请求与响应的元数据
- 性能监控:统计方法执行时间或请求耗时
- 限流与防刷:对频繁请求或异常请求进行限流或封禁
请求校验拦截器实现
本章将重点介绍如何在 Tio-Boot 中编写和配置“请求校验拦截器”(HttpRequestValidationInterceptor
),实现对缺失必填 Header 的拦截、封禁高频“无头”请求的功能,并演示如何在启动配置类中注册该拦截器。
1. 设计思路
- 无头请求判定:当请求缺少关键 Header(例如
from
)时,认为该请求不合法。 - 计数与阈值:统计同一 IP 的“无头请求”次数,超过设定阈值(如 10 次)后,将该 IP 加入黑名单(可扩展为持久化到 Redis 或防火墙规则)。
- 返回响应:对于每一次无头请求,都返回 HTTP 403 并主动关闭连接。
2. 自定义拦截拦截器校验逻辑
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import com.litongjava.tio.http.common.HttpRequest;
import com.litongjava.tio.http.common.HttpResponse;
import com.litongjava.tio.http.common.RequestLine;
import com.litongjava.tio.http.server.intf.HttpRequestInterceptor;
/**
* 应用级请求校验拦截器
* 1. 检查请求是否包含必要 Header
* 2. 累计无头请求次数,超过阈值则封禁 IP
*/
public class AppRequestValidationInterceptor implements HttpRequestInterceptor {
// 存储每个 IP 的无头请求计数
private final ConcurrentMap<String, AtomicInteger> badCount = new ConcurrentHashMap<>();
private static final int MAX_BAD = 10;
@Override
public HttpResponse doBeforeHandler(HttpRequest request, RequestLine requestLine, HttpResponse httpResponse) throws Exception {
String from = request.getHeader("from");
String clientIp = request.channelContext.getClientNode().getIp();
// 如果缺少 from Header,则视为无头请求
if (from == null) {
// 累加计数
int count = badCount.computeIfAbsent(clientIp, k -> new AtomicInteger()).incrementAndGet();
// 返回 403,主动关闭连接
httpResponse.setStatus(403);
httpResponse.setHeader("Connection", "close");
httpResponse.setKeepConnection(false);
// 超过阈值,执行封禁逻辑
if (count >= MAX_BAD) {
blockIp(clientIp);
}
return httpResponse;
} else {
//必须返回null,让请求继续向后执行
return null;
}
}
/**
* 封禁 IP(可根据实际需求扩展为:加入 Redis、更新防火墙规则等)
*/
private void blockIp(String ip) {
// TODO: 将 IP 持久化到黑名单,比如 Redis 或防火墙规则
}
@Override
public void doAfterHandler(HttpRequest request, RequestLine requestLine, HttpResponse response, long cost) {
// 后置处理:目前无操作
}
}
3. 在 Tio-Boot 中配置与使用
为了使上述拦截器生效,需要在应用启动配置类中注册它。Tio-Boot 提供了通过注解和初始化方法来完成这一操作的能力。
import com.litongjava.annotation.AConfiguration;
import com.litongjava.annotation.Initialization;
import com.litongjava.tio.boot.server.TioBootServer;
@AConfiguration
public class InterceptorConfiguration {
/**
* 应用初始化时注册请求校验拦截器
*/
@Initialization
public void config() {
// 获取 Tio-Boot 服务器单例
TioBootServer server = TioBootServer.me();
// 创建并注册自定义拦截器
AppRequestValidationInterceptor validationInterceptor = new AppRequestValidationInterceptor();
server.setHttpRequestValidationInterceptor(validationInterceptor);
}
}
说明:
@AConfiguration
标记该类为配置类,需被框架扫描。@Initialization
标记的方法在应用启动时被调用。TioBootServer.me()
返回 TioBootServer 单例,setHttpRequestValidationInterceptor(...)
用于替换默认的请求校验拦截器。
4.拓展与优化
黑名单持久化
- 将被封禁的 IP 写入 Redis、数据库或防火墙规则,重启后依然生效;
- 定期清理过期或临时封禁 IP。
动态阈值与告警
- 根据应用运行时负载或安全策略动态调整
MAX_BAD
; - 当某个 IP 次数激增时,可触发告警通知运维人员。
- 根据应用运行时负载或安全策略动态调整
白名单机制
- 对某些受信任的 IP 段或内网地址跳过校验。
多维度安全校验
- 除了 Header 校验,还可结合签名校验、令牌校验或验证码等手段;
- 对请求频率、请求体大小、URL 路径等进行限流或过滤。
5.小结
本文介绍了如何在 Tio-Boot 框架中编写一个“请求校验拦截器”,该拦截器能够在请求到达业务处理器前,验证请求是否合法、统计无头请求并在超过阈值后封禁 IP。通过注解式配置,可轻松将该拦截器集成到项目中。实际生产环境中,可根据业务需求进一步扩展持久化、告警及白名单等功能,以提升应用的安全防护能力。
普通拦截器
一、概述
在 Tio‑Boot 中,HTTP 拦截器(Interceptor)可用于对进出的请求进行统一控制,例如:权限校验、日志记录、限流等。通过配置拦截器模型(HttpInterceptorModel
),您可以灵活地指定哪些 URL 应被拦截(blockedUrls
),哪些 URL 应被放行(allowedUrls
),从而实现精细化的请求管理。
二、核心类说明
1. HttpInterceptorModel
拦截器的配置模型,包含:
- 名称
name
:拦截器标识。 - 放行列表
allowedUrls
:一组明确允许的 URL 模式。 - 拦截列表
blockedUrls
:一组需要拦截的 URL 模式。 - 拦截器实例
interceptor
:实现HttpRequestInterceptor
接口的处理逻辑。
常用方法:
// 设置名称
HttpInterceptorModel model = new HttpInterceptorModel()
.setName("exampleInterceptor");
// 添加单个/多个放行 URL
model.addAllowUrl("/admin/login");
model.addAllowUrls("/public/**", "/status");
// 添加单个/多个拦截 URL
model.addBlockUrl("/admin/**");
model.addAllowUrls("/api/private/**", "/secure/*");
// 绑定拦截器实现
model.setInterceptor(new YourCustomInterceptor());
注意
- 同一路径不能同时出现在
allowedUrls
和blockedUrls
中。- 支持通配符:
/**
匹配所有子路径,/*
匹配一级子路径。
2. HttpInteceptorConfigure
拦截器配置管理器,用于集中管理所有拦截器模型。
HttpInteceptorConfigure configure = new HttpInteceptorConfigure();
configure.add(model); // 添加拦截器
configure.remove("name"); // 按名称移除拦截器
List<HttpInterceptorModel> list = configure.getInteceptors(); // 获取所有模型
3. DefaultHttpRequestInterceptorDispatcher
执行链中的调度器,负责遍历所有 HttpInterceptorModel
,并在请求处理前后调用相应的拦截器方法。
doBeforeHandler
:在业务处理前执行。- 若返回非
null
的HttpResponse
,则后续业务和拦截器链将被短路。
- 若返回非
doAfterHandler
:在业务处理后执行。
三、在 TioBootServer 中注册拦截器
在启动类或配置类中,通过 TioBootServer
将自定义的拦截器配置注入到服务器:
import com.litongjava.annotation.AConfiguration;
import com.litongjava.annotation.Initialization;
import com.litongjava.tio.boot.http.interceptor.HttpInteceptorConfigure;
import com.litongjava.tio.boot.http.interceptor.HttpInterceptorModel;
import com.litongjava.tio.boot.server.TioBootServer;
@AConfiguration
public class InterceptorConfiguration {
@Initialization
public void init() {
// 1. 构建一个全局拦截器模型
HttpInterceptorModel global = new HttpInterceptorModel()
.setName("globalInterceptor")
.addBlockUrl("/**") // 拦截所有路径
.addAllowedUrl("/health") // 放行健康检查接口
.setInterceptor(new GlobalInterceptor());
// 2. 创建配置管理器并添加模型
HttpInteceptorConfigure config = new HttpInteceptorConfigure();
config.addInterceptor(global);
// 3. 注入到 TioBootServer
TioBootServer.me().setHttpInteceptorConfigure(config);
}
}
四、自定义拦截器示例
自定义拦截器需实现 HttpRequestInterceptor
接口,示例中将请求日志打印到控制台:
package com.litongjava.demo.interceptor;
import com.litongjava.tio.http.common.HttpRequest;
import com.litongjava.tio.http.common.HttpResponse;
import com.litongjava.tio.http.common.RequestLine;
import com.litongjava.tio.http.server.intf.HttpRequestInterceptor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class GlobalInterceptor implements HttpRequestInterceptor {
@Override
public HttpResponse doBeforeHandler(
HttpRequest request,
RequestLine requestLine,
HttpResponse originalResponse) throws Exception
{
log.info("[Before] {} {}", requestLine.getMethod(), requestLine.getPath());
// 返回 null 表示继续执行后续拦截器和业务处理
return null;
}
@Override
public void doAfterHandler(
HttpRequest request,
RequestLine requestLine,
HttpResponse response,
long costMillis) throws Exception
{
log.info("[After] {} {} -> {} ({} ms)",
requestLine.getMethod(),
requestLine.getPath(),
response.getStatus(),
costMillis);
}
}
五、URL 匹配与执行逻辑
匹配顺序
DefaultHttpRequestInterceptorDispatcher
会依次遍历所有已注册的HttpInterceptorModel
。拦截判定
- 若请求 URL 与某个模型的
blockedUrls
任一模式匹配,且不在该模型的allowedUrls
中,则视为需拦截。 - 在
doBeforeHandler
中若返回非空HttpResponse
,则直接返回该响应,不再执行后续拦截器与业务逻辑。
- 若请求 URL 与某个模型的
通配符规则
/api/**
:匹配/api
及其所有子路径。/static/*
:仅匹配一级子路径,如/static/logo.png
。
六、最佳实践
- 分层注册:可根据业务模块,将拦截器按职责拆分成多个模型,如认证、授权、日志、限流等,按需组合。
- 精确放行:尽量将
allowedUrls
配置得更精细,例如放行静态资源、健康检查、登录回调等。 - 性能考量:拦截器链中的执行逻辑应尽量轻量,避免阻塞或耗时操作;如需复杂处理,可异步执行或交由专用服务。
- 单元测试:对自定义拦截器逻辑编写单元测试,验证不同 URL 下的拦截与放行行为。
七、总结
通过以上配置,您可以在 Tio‑Boot 应用中轻松地管理 HTTP 请求的拦截与放行,实现统一的安全、限流、监控等功能。拦截器模型与调度器解耦,配置灵活且可扩展。实践中可结合业务需求,定制多层拦截策略,进一步提升系统的健壮性与可维护性。