4. 拦截链路设计:API网关拦截、微服务拦截、数据库拦截、前端路由拦截

多租户SaaS系统的鉴权不能依赖单一拦截点。攻击者可能绕过前端直接调用API,也可能通过内部服务间通信跳过网关。因此,必须在请求入口、服务边界、数据访问层、用户界面四个维度建立拦截链路,形成纵深防御体系。每一层拦截失败时,后续层仍能兜底,确保租户隔离不被突破。

4.1 四层拦截链路总览

下表对比了四层拦截的核心职责、拦截粒度与典型技术实现:

拦截层 拦截位置 拦截粒度 核心职责 典型技术
API网关拦截 系统入口 请求级 全局Token校验、租户识别、限流、IP黑白名单 Kong / APISIX / Spring Cloud Gateway
微服务拦截 服务边界 接口级 细粒度权限校验、资源归属校验、内部服务认证 Spring Security / OPA / 自定义Filter
数据库拦截 数据访问层 行级 强制租户ID过滤、行级安全策略、SQL改写 PostgreSQL RLS / MyBatis拦截器 / Hibernate Filter
前端路由拦截 用户界面 页面级 路由守卫、菜单权限、按钮级可见性控制 Vue Router / React Router / 动态路由
设计原则:每一层拦截应独立可回滚。当某一层策略需要变更时,通过CI/CD流水线单独发布该层配置,不影响其他拦截层的正常运行。

4.2 API网关拦截:第一道防线

API网关是外部请求进入系统的唯一入口。网关层拦截负责快速失败,在请求到达业务服务之前完成基础鉴权。

  • Token校验:验证JWT签名、过期时间、issuer合法性。无效Token直接返回401。
  • 租户识别:从请求头(如X-Tenant-ID)或JWT中提取租户标识,注入请求上下文。
  • 限流与熔断:按租户维度进行速率限制,防止单个租户的异常流量影响全局。
  • 路径白名单:公开接口(如登录、注册、健康检查)跳过鉴权。
# Kong网关鉴权插件配置示例
plugins:
  - name: jwt
    config:
      key_claim_name: "iss"
      secret_is_base64: false
      claims_to_verify:
        - "exp"
        - "nbf"
  - name: rate-limiting
    config:
      minute: 100
      policy: local
      fault_tolerant: true
      hide_client_headers: false
      redis_host: "redis-cluster.example.com"
回滚策略:网关插件配置应版本化管理。当新鉴权规则导致大量误拦截时,通过CI/CD快速回滚至上一版插件配置,恢复时间应控制在1分钟以内。

4.3 微服务拦截:服务间鉴权与细粒度权限

即使请求通过了网关,微服务内部仍需二次校验。因为服务间调用(gRPC、消息队列)可能不经过网关,且网关无法感知业务层面的资源归属关系。

  • 内部服务认证:服务间通信使用mTLS或预共享Token,防止未授权服务调用。
  • 资源归属校验:验证当前租户是否有权操作指定资源。例如:租户A不能删除租户B的订单。
  • 角色与权限:基于RBAC或ABAC模型,校验用户是否具备执行当前操作的权限。
// Spring Security 微服务拦截示例
@PreAuthorize("@tenantSecurity.hasAccess(#orderId)")
@PostMapping("/orders/{orderId}/cancel")
public ResponseEntity<Order> cancelOrder(@PathVariable String orderId) {
    // 业务逻辑
}
常见陷阱:微服务拦截层容易忽略内部调用链的鉴权。务必为所有服务间接口添加认证机制,避免“内部信任”漏洞。

4.4 数据库拦截:最后一道数据防线

数据库拦截是防止数据泄露的兜底策略。即使上层鉴权全部失效,数据库层仍能强制隔离租户数据。

实现方式 原理 优点 缺点
PostgreSQL RLS 行级安全策略,自动附加WHERE tenant_id = current_setting('app.tenant_id') 强制隔离,无需修改SQL 数据库连接需设置租户上下文
MyBatis拦截器 拦截Executor,动态追加租户ID过滤条件 灵活,支持多数据源 需维护拦截器逻辑,可能遗漏某些查询
Hibernate Filter ORM级过滤器,自动注入租户条件 与JPA深度集成 仅适用于Hibernate场景
-- PostgreSQL RLS 策略示例
CREATE POLICY tenant_isolation ON orders
    FOR ALL
    USING (tenant_id = current_setting('app.tenant_id')::UUID);
回滚优先级:数据库拦截策略变更风险最高。建议在CI/CD流水线中设置“数据库策略变更”为手动审批步骤,并配备自动回滚脚本。

4.5 前端路由拦截:用户体验与权限展示

前端拦截不提供安全防护,但能提升用户体验,避免用户看到无权限的菜单或页面后产生困惑。

  • 路由守卫:在路由跳转前检查用户Token和权限。无权限时重定向至403页面或登录页。
  • 动态路由:根据用户角色动态生成可访问的路由表,未授权路由不注册。
  • 按钮级权限:通过自定义指令或组件控制“新增/编辑/删除”按钮的可见性。
// Vue Router 路由守卫示例
router.beforeEach(async (to, from, next) => {
  const token = store.state.token;
  if (!token && to.path !== '/login') {
    return next('/login');
  }
  const hasPermission = await store.dispatch('checkPermission', to.meta.permission);
  if (!hasPermission) {
    return next('/403');
  }
  next();
});
注意:前端拦截仅作为辅助手段。所有敏感操作必须在后端重复校验,前端不可信。

4.6 四层拦截链路协作流程

下图展示了请求从用户到数据库的完整拦截链路,以及每一层失败时的回滚路径:

四层拦截链路协作与回滚路径 用户请求 前端路由拦截 路由守卫 / 动态菜单 / 按钮权限 API网关拦截 Token校验 / 租户识别 / 限流 微服务拦截 资源归属校验 / RBAC / 内部认证 数据库拦截 RLS / SQL改写 / 租户ID强制过滤 回滚策略 • 前端:回滚路由配置 • 网关:回滚插件版本 • 微服务:回滚权限策略 • 数据库:回滚RLS策略 每层独立版本化 CI/CD流水线自动回滚 回滚时间目标:< 1分钟

4.7 拦截链路配置的版本化与回滚

每一层拦截策略都应作为独立配置模块纳入CI/CD流水线。下表展示了各层配置的版本化策略:

拦截层 配置存储 版本化方式 回滚触发条件 回滚耗时目标
API网关 声明式YAML / 数据库 Git + 配置中心 鉴权误拦截率 > 5% < 30秒
微服务 代码注解 / 外部策略文件 Git分支 + 灰度发布 权限校验异常数上升 < 2分钟
数据库 迁移脚本 / 策略SQL Flyway + 版本号 数据查询超时或隔离失效 < 5分钟
前端 JSON配置 / 路由文件 Git + 静态资源版本 页面白屏或路由异常 < 1分钟
最佳实践:在CI/CD流水线中为每一层拦截配置添加“预发布验证”阶段。使用自动化测试模拟跨租户访问、越权操作等场景,验证新策略不会破坏现有隔离规则后再推送到生产环境。