# 安全设计 (Security) 本文档描述 tmpl-api 服务的安全架构、认证授权策略、数据保护措施和合规基线。 --- ## 1. 认证与授权 ### 1.1 当前状态 当前模板处于 `permitAll()` 状态,SecurityFilterChain 未启用身份验证。这是因为模板 的首要目标是演示分层架构和多租户设计,认证机制在实际项目中根据需求集成。 ### 1.2 规划路线图 | 阶段 | 方案 | 说明 | |------|------|------| | Phase 1(当前) | `permitAll()` | 模板演示阶段 | | Phase 2 | JWT Bearer Token(`spring-boot-starter-oauth2-resource-server`) | 服务作为资源服务器验证 JWT | | Phase 3 | OAuth2 + RBAC | 结合权限服务,细粒度角色控制 | ### 1.3 JWT 集成指引(Phase 2 参考) 启用 JWT 后,SecurityConfig 应调整为:要求所有 `/api/**` 请求携带有效的 Bearer Token;Actuator 链保持独立(`@Order(1)`),管理端口不经过 JWT 校验;JWT Claims 中应包含 `tenantId` 字段,用于与 `X-Tenant-Id` Header 交叉校验。 --- ## 2. 多租户信任边界 ### 2.1 信任模型 ``` [Client] --X-Tenant-Id: 5--> [API Gateway / Auth Layer] --X-Tenant-Id: 5--> [tmpl-api] ↑ 验证 tenantId 与 token 一致 ``` **关键原则**:`X-Tenant-Id` Header 不得直接信任来自公网客户端的值。在生产部署中, API 网关或认证层必须从 JWT Token / Session 中提取已验证的 tenantId,并覆盖或校验 请求头中的值。tmpl-api 服务本身假设上游已完成校验。 ### 2.2 防护措施 | 层级 | 责任 | |------|------| | API Gateway | 从 JWT 提取 tenantId,注入 X-Tenant-Id Header,拒绝不匹配的请求 | | tmpl-api SecurityFilter | 提取 X-Tenant-Id 并存入 TenantContext (ThreadLocal),缺失时返回 400 | | Application Layer | 所有查询自动附加 tenantId 条件(通过 Repository 方法签名) | | Database | 建议在关键表上创建 Row-Level Security Policy(PostgreSQL RLS)作为最后防线 | ### 2.3 禁止行为 不得允许一个租户访问另一个租户的数据。Controller 不得接受 URL Path 中的 tenantId 参数覆盖 Header 值。日志中记录 tenantId 以便审计。 --- ## 3. Actuator 端点安全 ### 3.1 暴露策略 参见 [observability.md](observability.md) 第 5 节。核心原则: 白名单端点(health、info、prometheus、metrics、caches)通过 `ActuatorSecurityConfig`(`@Order(1)`)放行。所有未列入白名单的端点(如 env、beans、heapdump、shutdown)均被拒绝。管理端口在 prod 环境与业务端口分离(9090 vs 8080)。 ### 3.2 生产加固 在生产环境中,管理端口 9090 必须通过以下至少一种方式加固:Kubernetes NetworkPolicy 仅允许 Prometheus 和运维 namespace 访问;在反向代理层启用 Basic Auth;启用 mTLS(适用于 Service Mesh 场景)。 --- ## 4. 敏感数据处理 ### 4.1 传输安全 | 通道 | 要求 | |------|------| | 客户端 → Gateway | HTTPS (TLS 1.2+) | | Gateway → 服务 | 集群内部:明文(依赖 NetworkPolicy)或 mTLS(Service Mesh) | | 服务 → 数据库 | `sslmode=require`(生产环境) | | 服务 → Redis | 启用 `requirepass` + TLS(如 Redis 6+) | ### 4.2 存储安全 数据库密码、Redis 密码等敏感配置通过 Kubernetes Secret 注入(参见 `deploy/base/secret.yaml`),不存放在 ConfigMap 或代码仓库中。日志中禁止打印完整的数据库连接 URL、密码、或用户敏感数据(如订单金额可以记录,但身份证号、银行卡号不可)。 ### 4.3 密钥轮换 建议通过 External Secrets Operator 或 Vault 管理 Secret 的生命周期,实现定期轮换。 --- ## 5. 依赖漏洞管理 ### 5.1 工具链 | 工具 | 用途 | 频率 | |------|------|------| | OWASP Dependency-Check | Maven 插件 `dependency-check-maven`,CI 中运行 | 每次构建 | | GitHub Dependabot | 自动 PR 升级有漏洞的依赖 | 每日扫描 | | SpotBugs + FindSecBugs | 静态代码安全分析 | 每次构建 | | Trivy | Docker 镜像漏洞扫描 | CI/CD 镜像构建后 | ### 5.2 漏洞响应流程 发现 CVSS >= 7.0 的漏洞时,24 小时内评估影响并创建修复 Issue;CVSS >= 9.0 立即启动紧急修复。 ### 5.3 安全基线检查清单 项目交付前应确认:HTTPS 已启用(或在 Gateway 层终止 TLS);Actuator 非白名单端点不可公网访问;数据库连接使用 Secret 注入;`X-Tenant-Id` 上游已验证;OWASP Dependency-Check 无 CVSS >= 7.0 漏洞;Docker 镜像使用非 root 用户运行(参见 Dockerfile `USER 1001`);Flyway 迁移不含 `DROP` 或 `TRUNCATE`(除非有明确的变更单号)。 --- ## 6. 漏洞披露 参见仓库根目录 [SECURITY.md](../SECURITY.md),定义了漏洞报告渠道和响应 SLA。