多租户系统需动态解析origin头识别租户并校验合法性,合法时精确回传access-control-allow-origin,按租户元数据差异化配置cors头与凭据策略,且预检请求必须在中间件完成租户上下文匹配。

多租户系统中,不同租户前端可能部署在不同域名(如 tenant-a.example.com、tenant-b.example.com、admin.myapp.io),不能简单用通配符或固定白名单。CORS 配置必须动态识别请求来源,并按租户策略响应,否则会引发安全风险或访问失败。
识别租户来源:靠 Origin 头 + 域名路由规则
浏览器发起跨域请求时,自动携带 Origin 请求头(如 Origin: https://shop.tenant-x.com)。服务端需解析该值,映射到对应租户身份:
- 提取主域名或子域名(如从
https://client.tenant-123.com提取tenant-123) - 查租户配置表或缓存,确认该域名是否合法、属于哪个租户、是否启用 API 访问
- 拒绝非法 Origin(如伪造的
Origin: https://evil.com),直接返回 403 或空响应头
动态设置 Access-Control-Allow-Origin
不能写死单个域名,也不能用 *(尤其开启 credentials 时无效)。正确做法是将校验后的 Origin 值原样回传:
- 若 Origin 合法且匹配租户白名单 → 响应头设为
Access-Control-Allow-Origin: https://client.tenant-123.com - 若请求带 Cookie(
withCredentials: true)→ 必须精确匹配,不可用通配符 - 避免拼接或反射 Origin(如
Origin: javascript:alert(1)),需严格校验协议+域名格式
按租户差异化控制其他 CORS 头
不同租户对方法、头、凭证的要求可能不同。例如:
- 租户 A 允许
POST /api/v1/orders,但租户 B 仅允许GET - 租户 C 要求携带
X-Tenant-ID自定义头,而租户 D 不需要 - 后台管理租户(admin)允许凭据,SaaS 客户端租户默认禁用凭据
这些策略应在租户元数据中定义,并在中间件中读取应用,例如:
Spring Boot 示例片段:registry.addMapping("/api/**")
.allowedOrigins(tenantConfig.getAllowedOrigins()) // 动态列表
.allowedMethods(tenantConfig.getAllowedMethods())
.allowedHeaders(tenantConfig.getAllowedHeaders())
.allowCredentials(tenantConfig.isCredentialsEnabled());
预检请求(OPTIONS)必须支持租户上下文
复杂请求(如含 Authorization 或 Content-Type: application/json)会触发预检。此时请求不带租户标识参数,仅靠 Origin 头判断:
- CORS 中间件必须在 OPTIONS 阶段完成 Origin 校验和租户匹配
- 确保 OPTIONS 响应包含完整 CORS 头(
Allow-Origin、Allow-Methods等),且与后续实际请求一致 - 不要把租户逻辑放到 Controller 层——预检请求不会进 Controller
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











