2. 鉴权与拦截链路概述

在多租户 SaaS 架构中,每一次请求从进入网关到抵达业务逻辑,必须经过严格的鉴权与拦截链路。本章厘清两个核心概念(Authentication vs Authorization)、两种拦截机制(Interceptor vs Filter),并给出完整的请求链路全景图。

2.1 鉴权(Authentication)与授权(Authorization)的区别

鉴权与授权是安全体系中经常被混淆的两个环节,但职责完全不同:

维度 鉴权(Authentication) 授权(Authorization)
核心问题 你是谁? 你能做什么?
执行时机 请求链路最前端 鉴权通过之后
校验内容 Token / Session / 证书 角色 / 权限 / 租户隔离策略
失败结果 401 Unauthorized 403 Forbidden
多租户场景 验证租户身份 + 用户身份 验证租户内资源访问范围
实践要点:鉴权失败直接阻断请求,不进入业务逻辑;授权失败通常返回明确错误码,便于前端展示权限不足提示。

2.2 拦截器(Interceptor)与过滤器(Filter)的作用

在 Java Web 体系中,Filter 和 Interceptor 是两种常见的请求拦截机制,它们在执行层级、作用范围和适用场景上存在明显差异:

对比项 Filter(过滤器) Interceptor(拦截器)
规范层级 Servlet 规范 Spring MVC 框架
作用范围 所有 URL 请求(包括静态资源) 仅 Controller 请求
执行顺序 先于 Interceptor 执行 在 Filter 之后、Controller 之前
典型用途 字符编码、跨域、XSS 过滤、Token 解析 权限校验、日志记录、租户上下文注入
是否可获取 Spring Bean 需特殊配置 原生支持
推荐策略:Filter 负责全局性、低层级的预处理(如 Token 解析、租户识别);Interceptor 负责业务相关的鉴权与授权校验,便于复用 Spring 的依赖注入和 AOP 能力。

2.3 请求链路全景图

下图展示了一次完整的多租户 SaaS 请求从进入网关到返回响应的鉴权与拦截链路:

多租户 SaaS 鉴权拦截链路全景图 请求链路鉴权与拦截全景图 外部请求 网关层(API Gateway) 路由 · 限流 · 基础 Token 校验 Filter 链(Servlet 容器) 字符编码 · 跨域 · XSS · Token 解析 Interceptor 链(Spring MVC) 鉴权 · 授权 · 租户上下文注入 Controller 业务逻辑 链路说明 1. 外部请求进入网关 2. 网关做基础路由与限流 3. Filter 链预处理请求 4. Interceptor 链鉴权授权 5. 注入租户上下文 6. 进入 Controller 业务 7. 异常时统一拦截返回 失败状态码: 鉴权失败 → 401 授权失败 → 403 限流/其他 → 429/500

2.4 多租户上下文注入时机

在 Interceptor 链中,鉴权通过后需要立即将租户信息注入到当前请求上下文,供后续业务逻辑使用:

// 自定义 TenantInterceptor 示例
public class TenantInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {
        // 1. 从 Token 中解析租户 ID
        String tenantId = extractTenantId(request);

        // 2. 校验租户有效性(鉴权)
        if (tenantId == null || !tenantService.isValid(tenantId)) {
            response.sendError(HttpStatus.UNAUTHORIZED.value(), "无效租户");
            return false;
        }

        // 3. 校验租户内权限(授权)
        if (!permissionService.hasAccess(tenantId, request.getRequestURI())) {
            response.sendError(HttpStatus.FORBIDDEN.value(), "权限不足");
            return false;
        }

        // 4. 注入租户上下文
        TenantContextHolder.set(tenantId);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler, Exception ex) {
        // 5. 请求结束后清理上下文,防止内存泄漏
        TenantContextHolder.clear();
    }
}
常见陷阱:租户上下文使用 ThreadLocal 存储时,务必在 afterCompletion 或 finally 块中清理,否则线程池复用会导致租户信息串号,引发严重的数据泄露事故。

2.5 链路拦截决策矩阵

在实际部署中,不同层级的拦截器负责不同粒度的校验,以下矩阵帮助团队快速决策:

拦截层级 校验内容 失败处理 配置方式
网关层 Token 格式、签名、过期时间 直接返回 401,不进入内网 路由规则 + 全局过滤器
Filter 链 请求编码、跨域头、基础安全过滤 抛出 ServletException web.xml 或 @WebFilter
Interceptor 链 租户身份、资源权限、数据隔离 返回 401/403 JSON 响应 WebMvcConfigurer 注册
AOP 切面 方法级细粒度权限、数据脱敏 抛出业务异常 @Aspect + 自定义注解

通过上述分层设计,多租户 SaaS 系统能够实现从网络层到业务层的全链路鉴权与拦截,既保证了安全性,又保持了各层职责的清晰分离。