系统性讲解AI平台多租户安全的完整攻击面:数据库、行级安全、向量库、RAG索引、缓存、网络隔离等74个隔离边界与验证方法。
多租户允许一个 AI 平台服务于多个独立用户、组织、团队或客户,同时共享应用基础设施。
这一架构产生了一个根本性的安全需求:
租户必须永远无法访问、修改、推断或影响另一个租户的数据或资源,除非存在明确授权的跨租户操作。
对于 AI 平台而言,租户隔离的范围比数据库隔离要广。租户边界可能存在于:
管理接口
因此,一个平台即使拥有完美安全的数据库,仍可能因缓存、对象存储路径、向量搜索、后端 Worker 或 AI 记忆系统中的漏洞而遭受跨租户攻击。
租户应被视为一等安全边界。
Platform
│
├── Tenant A
│ ├── Users
│ ├── Projects
│ ├── Files
│ ├── Conversations
│ ├── AI generations
│ └── Vector data
│
├── Tenant B
│ ├── Users
│ ├── Projects
│ ├── Files
│ ├── Conversations
│ └── Vector data
│
└── Tenant C
├── Users
├── Projects
├── Files
├── Conversations
└── Vector data
安全模型必须阻止:
Tenant A → Tenant B data
Tenant B → Tenant C data
Tenant C → Tenant A data
即使攻击者知道:
另一个租户的标识符
另一个对象的标识符
会话标识符
向量文档标识符
内部任务标识符
因此,租户 ID 必须被视为授权属性,而非安全密钥。
每个经过身份验证的请求都应具有可信的租户上下文。
简化的请求上下文可能如下:
Request
↓
Authentication
↓
User identity
↓
Membership lookup
↓
Tenant context
↓
Authorization
↓
Resource access
type RequestContext = {
userId: string;
tenantId: string;
roles: string[];
permissions: string[];
};
重要的规则是:
应用必须从可信的身份验证和授权数据中推导租户成员资格,而不是信任客户端任意提供的租户标识符。
不安全的概念模式:
POST /api/files
{
tenantId: "tenant-b"
}
如果服务器直接信任该值。
更安全的概念模式:
Authenticated user
↓
Membership database
↓
Authorized tenant
↓
Server-generated tenant context
↓
Database query
一个用户可以属于一个或多个租户。
User
├── Tenant A → owner
├── Tenant B → member
└── Tenant C → viewer
因此,授权应区分:
identity ≠ tenant membership ≠ resource permission
用户通过身份验证并不自动意味着他们可以访问每个租户。
一个健壮的模型可以包含:
users
organizations
memberships
roles
permissions
projects
resources
示例关系:
User
↓
Membership
↓
Tenant
↓
Project
↓
Resource
这支持分层授权。
一种常见的共享数据库架构是:
Single Database
│
├── users
├── tenants
├── memberships
├── projects
├── files
├── conversations
└── generations
每个租户拥有的记录都应包含租户标识符。
projects
--------------------------------
id
tenant_id
name
created_at
generations
--------------------------------
id
tenant_id
user_id
project_id
model
status
created_at
租户标识符应作为授权边界的一部分。
不要这样概念性地做:
SELECT *
FROM projects
WHERE id = $1;
而要这样:
SELECT *
FROM projects
WHERE id = $1
AND tenant_id = $2;
第二个条件至关重要。
最重要的多租户控制之一是对象级授权。
Tenant A
project_123
Tenant B
project_456
来自 Tenant A 的攻击者更改:
project_123
为
project_456
API 不得返回 Tenant B 的项目。
安全决策应该是:
这个经过身份验证的主体
是否有权在
这个租户内
访问这个资源?
用户是否已通过身份验证?
这可以防止不安全的直接对象引用和对象级授权失效模式。
数据库级行级安全可以提供额外的防御层。
Application authorization
+
Database authorization
=
Defense in depth
对于支持行级安全的数据库,策略可以根据活动租户上下文限制记录。
Current tenant = Tenant A
Allowed:
tenant_id = Tenant A
Denied:
tenant_id = Tenant B
tenant_id = Tenant C
这减少了对每个应用查询都完美无缺的依赖。
行级安全应作为应用授权的补充,而不是取代proper application design。
租户身份必须贯穿整个请求生命周期。
HTTP Request
↓
API Gateway
↓
Application
↓
Service
↓
Queue
↓
Worker
↓
Database
↓
Object Storage
如果在某一阶段租户上下文消失,隔离就会失效。
因此,作业应包含可信的租户上下文。
type GenerationJob = {
jobId: string;
tenantId: string;
userId: string;
projectId: string;
generationId: string;
};
Worker 应验证:
job.tenantId
matches
resource.tenantId
在处理作业之前。
AI 平台频繁使用异步处理。
User
↓
API
↓
Queue
↓
Worker
↓
AI Model
↓
Storage
一种危险的 Worker 设计可能只使用以下信息处理作业:
generationId
而不验证其租户。
更安全的设计是验证完整的归属链:
Job
↓
Generation
↓
Project
↓
Tenant
job.tenant_id
↓
generation.tenant_id
↓
project.tenant_id
所有相关关系应保持一致。
对象存储引入了另一个主要的租户边界。
bucket/
tenant-a/
project-1/
image.png
tenant-b/
project-7/
image.png
存储路径有助于组织,但仅靠路径不是授权。
攻击者不应仅因猜到:
tenant-b/project-7/image.png
就获得访问权限。
应用应在发放下载链接或签名 URL 之前进行授权。
推荐的概念流程:
User request
↓
Authenticate
↓
Authorize resource
↓
Verify tenant ownership
↓
Generate short-lived signed URL
↓
Download
签名 URL 应:
仅在授权后生成
限制为所需对象
防止意外重用
避免不必要的过长过期时间。
签名 URL 不应成为永久的替代身份验证机制。
RAG 系统产生了一个特别重要的多租户问题。
Tenant A documents
Tenant B documents
Tenant C documents
存储在一个向量数据库中。
一个简单的语义搜索可能检索到:
Tenant A query
↓
Global vector search
↓
Tenant B document
这是严重的信息隔离失效。
每次向量搜索都应包含可信的租户过滤器。
query embedding
+
tenant_id = current tenant
↓
vector search
↓
authorized documents only
租户边界必须在检索时或作为检索的一部分强制执行,而不是仅在返回结果后才进行过滤。
安全的 RAG 流水线应如下:
User
↓
Authentication
↓
Tenant authorization
↓
Tenant-specific retrieval
↓
Document authorization
↓
Context construction
↓
AI model
↓
Output policy checks
而不是:
User
↓
Global search
↓
Filter results afterward
在检索后过滤仍可能产生涉及以下内容的风险:
意外上下文泄漏
最安全的方法是防止未授权数据进入检索结果集。
长期 AI 记忆也必须感知租户。
Tenant A
└── User 1
└── Memory A
Tenant B
└── User 2
└── Memory B
系统必须阻止:
Tenant A request
↓
Memory retrieval
↓
Tenant B memory
记忆应有明确的归属元数据,例如:
tenant_id
user_id
conversation_id
project_id
memory_scope
记忆检索操作应强制执行这些边界。
缓存经常被忽视。
假设一个 API 存储:
cache["project:123"] = project_data
如果项目标识符是全局可寻址的,但授权不属于缓存设计的一部分,则第二个租户可能潜在地收到缓存数据。
更安全的概念性缓存键可以包含租户:
tenant:A:project:123
或者,更好的做法是,在返回缓存数据之前仍独立检查授权。
感知租户的缓存设计应适用于:
生成的媒体元数据
会话数据永远不应模棱两可地与多个租户关联。
会话应标识:
session_id
user_id
tenant_id
created_at
expires_at
当用户切换组织时,活动租户上下文应明确更新并重新授权。
应用不应假设:
same user = same tenant
因为一个用户可能属于多个租户。
队列也可能泄露信息。
queue:
job1 → Tenant A
job2 → Tenant B
job3 → Tenant C
Worker 不能认为仅凭任务标识符就足够了。
每个任务都应该携带经过验证的所有权上下文。
大型平台可能需要更强的基础设施隔离。
可能的架构:
Internet
↓
API Gateway
↓
Tenant-aware services
↓
Internal service network
↓
Data services
更高隔离级别的部署可能使用:
Tenant
↓
Dedicated namespace
↓
Dedicated service resources
↓
Dedicated database/schema
↓
Dedicated storage
正确的隔离级别取决于:
常见的多租户数据库模型包括:
模型 1 — 共享数据库,共享表
Database
└── Shared tables
└── tenant_id
模型 2 — 共享数据库,独立 Schema
Database
├── tenant_a_schema
├── tenant_b_schema
└── tenant_c_schema
提供更强的逻辑隔离,但引入了 Schema 管理复杂性。
模型 3 — 每个租户独立数据库
Tenant A → Database A
Tenant B → Database B
Tenant C → Database C
提供更强的隔离,但增加了:
模型 4 — 混合隔离
平台可以对租户进行分类。
Standard tenants
↓
Shared infrastructure
High-isolation tenants
↓
Dedicated infrastructure
这可以平衡成本和安全。
安全测试应考虑现实的失败模式。
场景 A — 标识符替换
Tenant A
↓
changes resource ID
↓
Tenant B resource
403 Forbidden
或等效的不泄露信息的响应。
场景 B — 租户参数操纵
tenant_id=A
↓
change to
tenant_id=B
authorization failure
场景 C — 存储路径操纵
Tenant A
↓
attempts Tenant B object path
access denied
场景 D — 向量过滤器移除
Tenant A
↓
attempts global vector search
query rejected
或系统自动应用可信的租户边界。
场景 E — 缓存冲突
Tenant A request
↓
cache entry
↓
Tenant B receives same entry
tenant-specific cache isolation
场景 F — 任务替换
Tenant A
↓
submits Tenant B job ID
authorization failure
AI 系统会产生额外的泄露通道。
Tenant A prompt
↓
retrieval
↓
Tenant B document
↓
LLM
↓
Tenant A response
模型本身可能不是原始的安全故障。
根本故障是:
unauthorized context → model
因此 AI 安全必须保护整个上下文管道。
Tenant
↓
Authorization
↓
Retrieval
↓
Context
↓
Model
↓
Output
如果多个租户共享 AI 模型服务,请求仍应携带租户感知的元数据。
request_id
tenant_id
user_id
model_id
policy_context
模型提供商或内部推理层不应意外地在租户之间混合对话状态。
无状态推理通常比共享可变模型会话状态更容易隔离。
如果客户数据用于模型改进,需要额外的控制。
租户的私有数据不应自动成为:
global training data
除非有适当的授权、治理和披露。
更安全的概念分离是:
Production user data
│
├── operational use
│
├── analytics
│
└── optional training pipeline
↓
explicit policy
↓
approved dataset
训练管道需要溯源和租户边界控制。
日志可能意外成为跨租户数据源。
logs:
tenant A prompt
tenant B prompt
tenant C prompt
普通租户用户不应获得访问全局日志的权限。
管理日志访问也应该:
敏感的 AI 提示词、上传的文档、令牌和生成的内容不应被不必要地写入日志。
分析系统可能意外合并租户信息。
Tenant A dashboard
↓
global aggregation
↓
Tenant B metrics
每个分析查询都应定义其预期范围。
user
project
tenant
platform
平台级分析需要提升的权限。
账单记录是租户敏感的。
租户只能访问:
its own invoices
its own subscriptions
its own usage
its own payment metadata
使用量计量也应该是租户感知的:
tenant_id
resource
quantity
timestamp
这可以防止一个租户的 AI 使用量被计入另一个租户。
通知也应包含租户上下文。
Tenant A
└── generation completed
Tenant B
└── generation failed
通知系统必须防止:
Tenant A user
↓
Tenant B notification
Webhook 应与正确的租户关联。
webhook_id
tenant_id
endpoint
secret_reference
event_type
事件生成应验证:
event.tenant_id
==
webhook.tenant_id
API 网关可以提供早期安全层。
可能的职责:
然而,下游服务仍应执行授权。
网关不应成为唯一的租户安全机制。
内部请求应携带可信上下文。
API
↓
Generation Service
↓
Storage Service
存储服务应该知道:
Which tenant?
Which user?
Which resource?
Which permission?
盲目信任客户端的任意请求头是不安全的。
租户上下文应来自可信的内部认证机制。
管理员会产生特殊风险。
管理员可能合法地访问多个租户,但这不意味着:
admin = unrestricted access
管理员访问仍应是:
支持工具应避免静默地模拟用户。
租户删除必须是全面的。
删除可能涉及:
Database
Storage
Vectors
Caches
Queues
Backups
Search indexes
AI memory
Analytics
Notifications
Webhooks
Logs
租户删除工作流应定义:
what is deleted
what is retained
why it is retained
retention duration
who authorized deletion
verification status
删除还应防止孤立资源。
当客户离开平台时:
Tenant disabled
↓
sessions revoked
↓
API credentials revoked
↓
webhooks disabled
↓
jobs stopped/cancelled
↓
access removed
↓
data lifecycle executed
这可以防止前用户继续访问租户资源。
一个严肃的平台应该系统地测试租户边界。
最低测试类别:
Authentication
Authorization
Database
Storage
Vectors
RAG
Memory
Cache
Queues
Workers
APIs
Webhooks
Notifications
Billing
Analytics
Admin tools
Deletion
Backups
有用的测试矩阵:
自动化测试应至少创建两个租户:
Tenant A
Tenant B
然后创建等效资源:
A/project
B/project
A user → A resource = allowed
A user → B resource = denied
B user → B resource = allowed
B user → A resource = denied
在每种资源类型上重复此操作。
一个有用的安全不变量是:
For every tenant-owned resource R:
request.tenant_id == R.tenant_id
在授予访问权限之前必须为真。
对于层级资源:
request.tenant
=
resource.project.tenant
=
resource.document.tenant
=
resource.vector.tenant
任何不匹配都应终止操作。
如果租户信息是:
系统应该失败关闭。
Unknown tenant
↓
DENY
Unknown tenant
↓
fallback to global scope
在多租户系统中,全局回退行为特别危险。
安全监控应检测异常的跨租户模式。
User repeatedly requesting foreign resource IDs
Large number of authorization failures
Unexpected tenant changes
Vector searches without tenant filters
Storage access outside tenant prefix
这些事件可能表示:
如果怀疑发生跨租户泄露:
步骤 1 — 隔离
禁用受影响的端点、工作流或集成。
步骤 2 — 确定范围
which tenants
which resources
which time period
which users
步骤 3 — 保留证据
授权决定
步骤 4 — 撤销暴露
临时凭证
步骤 5 — 纠正边界
修复授权或隔离失败。
执行有针对性的跨租户测试。
找出现有控制措施失效的原因。
一个安全的 multi-tenant AI 平台可以建模为:
Internet
│
▼
┌──────────────┐
│ API Gateway │
└──────┬───────┘
│
▼
Authentication
│
▼
Tenant Context
│
▼
Authorization
│
┌──────────────┼──────────────┐
▼ ▼ ▼
Database Storage AI Services
│ │ │
│ │ ┌────┴────┐
│ │ │ RAG │
│ │ │ Memory │
│ │ │ Models │
│ │ └─────────┘
│ │
└──────────────┼──────────────┐
│ │
Queue Cache
│ │
▼ ▼
Workers Tenant Scope
│
▼
Audit / Monitoring
每个分支都必须保持 tenant 边界。
以下规则应成为全平台工程要求:
每个 tenant 拥有的资源都有明确的所有权模型。
Tenant 身份源于可信的认证上下文。
永不相信客户端提供的 tenant ID。
每次对象访问都需要授权。
数据库查询强制执行 tenant 范围。
存储访问是 tenant 感知的。
向量检索是 tenant 感知的。
RAG 上下文是 tenant 感知的。
AI 记忆是 tenant 感知的。
缓存键和缓存授权是 tenant 感知的。
队列任务携带经过验证的 tenant 上下文。
Worker 验证资源所有权。
通知是 tenant 范围的。
账单记录是 tenant 范围的。
Webhook 是 tenant 范围的。
分析功能强制执行预期范围。
管理访问单独控制。
未知的 tenant 上下文失败闭合。
跨 tenant 测试自动化。
Tenant 隔离失效触发事件响应。
Multi-tenancy 绝不应该仅仅通过添加:
tenant_id
来实现。
真正的 multi-tenant 安全架构在整个平台上建立一致的边界:
Identity
↓
Tenant
↓
Authorization
↓
Data
↓
Storage
↓
Retrieval
↓
Memory
↓
Cache
↓
Queue
↓
Worker
↓
AI Model
↓
Output
↓
Audit
最重要的不变量是:
Tenant 只能访问属于该 tenant 的资源、计算、上下文和输出,或已明确授权可跨 tenant 使用的资源、计算、上下文和输出。
对于 AI 平台,此边界必须在敏感数据到达检索系统、AI 模型、缓存、Worker 或外部服务之前强制执行。
因此,安全的 multi-tenant 平台将 tenant 隔离视为系统级安全不变量,而不是在某个数据库查询中实现的功能。