RAGFlow 多租户多团队
企业级增强技术方案
基于 RAGFlow v0.25.6 — 多法人隔离 · 团队管理 · 权限控制 · 向量库分区
📅 编制日期:2026-06-08
📦 基线版本:v0.25.6
🔒 密级:内部
1 现状分析
1.1 RAGFlow 当前架构概览
RAGFlow v0.25.6 采用 Python Quart 后端 + React/TypeScript 前端 + Docker 微服务架构,核心组件包括:
| 组件 | 作用 |
ragflow-server | 主 API 网关与任务调度中心 |
ragflow-web | React 18 响应式 Web UI |
| Elasticsearch / Infinity / OpenSearch | 向量数据库 + 全文检索引擎 |
| MySQL / PostgreSQL | 关系型元数据存储 |
| MinIO / S3 | 对象存储(原始文档与切片元数据) |
| Redis / Valkey | 缓存与会话状态 |
1.2 当前数据模型(User-Tenant-UserTenant 三表关系)
┌──────────┐ ┌──────────────┐ ┌──────────┐
│ User │────<│ UserTenant │>────│ Tenant │
└──────────┘ └──────────────┘ └──────────┘
│
role (owner/member)
invited_by
status
- User:用户表,存储 email、password、nickname、access_token 等
- Tenant:租户表,每个用户注册时自动创建一个以其名字命名的默认租户
- UserTenant:用户-租户关联表,记录 role(owner/member)、invited_by、status
- Knowledgebase:知识库表,通过
tenant_id FK 归属租户,permission 字段控制可见性(me/team)
- Document:文档表,通过
kb_id FK 归属知识库
- Dialog / Agent:对话/智能体,通过
tenant_id 归属租户
1.3 当前团队模型局限
| 局限点 | 描述 |
| 角色单一 | 只有 owner 和 member 两种角色,无团队管理员角色 |
| 无邀请权 | 只有 owner 能邀请成员,member 无法邀请 |
| 权限粗粒度 | 知识库权限仅 me/team 两档,无文档级/操作级权限控制 |
| 无限流 | 没有基于用户/租户的 API 调用频率限制 |
| 无分区 | 向量数据未按租户物理/逻辑分区,仅依赖应用层 tenant_id 过滤 |
| 无多法人 | 租户之间无层级关系,无法表达法人-用户组-团队的多层结构 |
| 无空间 | 每个租户独立,无租户内公共空间与共享空间的概念 |
2 目标需求映射
| 编号 | 需求 | 对应技术领域 |
| R1 | 增加支持团队的知识库,同时支持系统管理员的文档管理功能 | 数据模型扩展 + RBAC |
| R2 | 为每个 team 设置团队管理员,用于管理团队成员和知识库 | 角色体系扩展 |
| R3 | 分配、修改用户权限、用户限流、用户授权 | 权限引擎 + 限流中间件 |
| R4 | 方案可复用 | 模块化设计 + 中间件抽象 |
| R5 | 适配多法人、多个用户组,各用户组之间实现数据的逻辑隔离 | 多层租户模型 + 数据隔离 |
| R6 | 向量数据库按照租户分区 | 向量库分区策略 |
| R7 | 用户访问隔离,为每个租户创建单独共享和公共空间 | 空间模型设计 |
3 总体架构设计
3.1 分层架构总览
┌─────────────────────────────────────────────────────────────────┐
│ API Gateway / Nginx │
│ (TLS 终结 / 限流 / 租户路由) │
├─────────────────────────────────────────────────────────────────┤
│ 认证鉴权层 (Auth Layer) │
│ JWT + OAuth2/OIDC + API Token 三路径认证 │
│ TenantContextMiddleware → 注入 tenant_id 上下文 │
├─────────────────────────────────────────────────────────────────┤
│ 权限引擎层 (RBAC Engine) │
│ 角色-权限矩阵 + ABAC 属性策略 + 操作级鉴权 │
├─────────────────────────────────────────────────────────────────┤
│ 业务服务层 (Business Services) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 租户管理 │ │ 团队管理 │ │ 知识库管理 │ │ 文档管理 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 用户管理 │ │ 空间管理 │ │ Agent管理 │ │ 限流管理 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ 数据访问层 (DAL) │
│ 租户上下文自动注入 → SQL 过滤 + 向量库分区路由 │
├─────────────────────────────────────────────────────────────────┤
│ 存储层 (Storage) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ MySQL/PG │ │ ES/Infy │ │ MinIO │ │ Redis │ │
│ │ 行级安全 │ │ 租户分区 │ │ 租户桶 │ │ Key前缀 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────┘
3.2 核心设计原则
| 原则 | 描述 |
| 租户上下文驱动 | 所有数据访问必须携带 tenant_id,由中间件统一注入,应用代码无感知 |
| 逻辑隔离为主 | 默认逻辑隔离(tenant_id 分区键),高安全租户可升级为物理隔离 |
| 可复用中间件 | 权限引擎、限流器、租户路由均设计为可插拔中间件 |
| 向下兼容 | 不破坏现有 API 契约,通过扩展字段和新增接口实现增强 |
4 数据模型设计
4.1 多层租户模型(法人 → 用户组 → 团队)
┌─────────────┐
│ Organization│ ← 法人实体(多法人隔离顶层)
│ (法人) │
└──────┬──────┘
│ 1:N
┌──────▼──────┐
│ UserGroup │ ← 用户组(部门/业务线级别隔离)
│ (用户组) │
└──────┬──────┘
│ 1:N
┌──────▼──────┐
│ Team │ ← 团队(协作单元,知识库归属主体)
│ (团队) │
└─────────────┘
4.2 新增/修改表结构
4.2.1 Organization(法人实体表)— 新增
CREATE TABLE organization (
id VARCHAR(32) PRIMARY KEY,
name VARCHAR(200) NOT NULL,
code VARCHAR(64) UNIQUE NOT NULL,
description TEXT,
logo TEXT,
status CHAR(1) DEFAULT '1',
isolation_level VARCHAR(16) DEFAULT 'logical', -- logical / physical
created_by VARCHAR(32),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);SQL
4.2.2 UserGroup(用户组表)— 新增
CREATE TABLE user_group (
id VARCHAR(32) PRIMARY KEY,
org_id VARCHAR(32) NOT NULL,
name VARCHAR(200) NOT NULL,
code VARCHAR(64) NOT NULL,
description TEXT,
parent_id VARCHAR(32), -- 支持树形结构
status CHAR(1) DEFAULT '1',
created_by VARCHAR(32),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_org_code (org_id, code)
);SQL
4.2.3 Tenant 表扩展
ALTER TABLE tenant ADD COLUMN org_id VARCHAR(32);
ALTER TABLE tenant ADD COLUMN user_group_id VARCHAR(32);
ALTER TABLE tenant ADD COLUMN tenant_type VARCHAR(16) DEFAULT 'team';
ALTER TABLE tenant ADD COLUMN space_config JSON;SQL
4.2.4 UserTenant 角色扩展
ALTER TABLE usertenant ADD COLUMN role VARCHAR(32) DEFAULT 'member';
-- 角色枚举:owner / team_admin / member / viewerSQL
4.2.5 OrgUser(法人-用户关联表)— 新增
CREATE TABLE org_user (
id VARCHAR(32) PRIMARY KEY,
org_id VARCHAR(32) NOT NULL,
user_id VARCHAR(32) NOT NULL,
role VARCHAR(32) DEFAULT 'member',
status CHAR(1) DEFAULT '1',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_org_user (org_id, user_id)
);SQL
4.2.6 UserGroupMember(用户组成员表)— 新增
CREATE TABLE user_group_member (
id VARCHAR(32) PRIMARY KEY,
group_id VARCHAR(32) NOT NULL,
user_id VARCHAR(32) NOT NULL,
role VARCHAR(32) DEFAULT 'member',
status CHAR(1) DEFAULT '1',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_group_user (group_id, user_id)
);SQL
4.2.7 Permission / Role 权限表 — 新增
CREATE TABLE permission (
id VARCHAR(32) PRIMARY KEY,
code VARCHAR(64) UNIQUE NOT NULL,
name VARCHAR(200) NOT NULL,
resource_type VARCHAR(32),
action VARCHAR(32),
description TEXT
);
CREATE TABLE role (
id VARCHAR(32) PRIMARY KEY,
code VARCHAR(64) UNIQUE NOT NULL,
name VARCHAR(200) NOT NULL,
scope VARCHAR(16) DEFAULT 'team',
description TEXT
);
CREATE TABLE role_permission (
role_id VARCHAR(32) NOT NULL,
permission_id VARCHAR(32) NOT NULL,
PRIMARY KEY (role_id, permission_id)
);
CREATE TABLE user_role (
id VARCHAR(32) PRIMARY KEY,
user_id VARCHAR(32) NOT NULL,
role_id VARCHAR(32) NOT NULL,
scope_type VARCHAR(16),
scope_id VARCHAR(32),
granted_by VARCHAR(32),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_user_role_scope (user_id, role_id, scope_type, scope_id)
);SQL
4.2.8 RateLimitQuota(限流配额表)— 新增
CREATE TABLE rate_limit_quota (
id VARCHAR(32) PRIMARY KEY,
scope_type VARCHAR(16) NOT NULL,
scope_id VARCHAR(32) NOT NULL,
api_path_pattern VARCHAR(255),
max_requests INT NOT NULL,
window_seconds INT NOT NULL DEFAULT 60,
max_tokens INT,
max_storage_mb INT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_scope_pattern (scope_type, scope_id, api_path_pattern)
);SQL
4.2.9 Space(空间表)— 新增
CREATE TABLE space (
id VARCHAR(32) PRIMARY KEY,
tenant_id VARCHAR(32) NOT NULL,
name VARCHAR(200) NOT NULL,
space_type VARCHAR(16) NOT NULL, -- public / shared / private
description TEXT,
created_by VARCHAR(32),
status CHAR(1) DEFAULT '1',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_tenant_space (tenant_id, name)
);SQL
空间类型说明:
public 租户内所有人可见(如公司公告知识库)
shared 租户内指定团队/成员可见(如项目组知识库)
private 仅创建者可见(个人知识库)
4.2.10 Knowledgebase 表扩展
ALTER TABLE knowledgebase ADD COLUMN space_id VARCHAR(32);
ALTER TABLE knowledgebase ADD COLUMN org_id VARCHAR(32);
ALTER TABLE knowledgebase ADD COLUMN user_group_id VARCHAR(32);SQL
4.3 完整 ER 关系图
Organization 1──N UserGroup 1──N Team(Tenant)
│ │ │
│ │ ├── Knowledgebase ── Document
│ │ ├── Dialog
│ │ ├── Agent
│ │ └── Space
│ │
├── OrgUser ──── User ──── UserTenant
│ UserRole
│
└── UserGroupMember RateLimitQuota
5 核心模块详细设计
5.1 角色与权限体系(RBAC + ABAC)
5.1.1 角色定义
| 角色 | 作用域 | 核心权限 |
| system_admin | 全局 | 管理所有法人、用户组、系统配置、文档管理 |
| org_admin | 法人 | 管理本法人下用户组、团队成员、法人级知识库 |
| group_admin | 用户组 | 管理本用户组下团队、用户组成员 |
| team_admin | 团队 | 管理团队成员、团队知识库、团队 Agent |
| member | 团队 | 使用授权的知识库和 Agent |
| viewer | 团队 | 只读访问授权资源 |
5.1.2 权限矩阵
| 资源/操作 | system_admin | org_admin | group_admin | team_admin | member | viewer |
| org:create | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| org:read | ✅ | ✅* | ❌ | ❌ | ❌ | ❌ |
| group:create | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |
| group:manage_members | ✅ | ✅ | ✅* | ❌ | ❌ | ❌ |
| team:create | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
| team:manage_members | ✅ | ✅ | ✅ | ✅* | ❌ | ❌ |
| team:manage_kb | ✅ | ✅ | ✅ | ✅* | ❌ | ❌ |
| kb:create | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| kb:read | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| kb:doc:upload | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| kb:doc:delete | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| agent:create | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| agent:use | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| dialog:chat | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
* 仅限本作用域内资源
5.1.3 权限引擎实现
class PermissionEngine:
def __init__(self, db_session):
self.db = db_session
async def check_permission(self, user_id: str, resource_type: ResourceType,
action: Action, scope_id: str = None) -> bool:
user_roles = await self._get_user_roles(user_id, resource_type, scope_id)
for ur in user_roles:
role_perms = await self._get_role_permissions(ur.role_id)
for perm in role_perms:
if perm.resource_type == resource_type.value and perm.action == action.value:
if ur.scope_id is None or ur.scope_id == scope_id:
return True
return await self._check_abac_policy(user_id, resource_type, action, scope_id)
def require_permission(resource_type: ResourceType, action: Action):
def decorator(func):
@wraps(func)
async def wrapper(*args, **kwargs):
user = get_current_user()
engine = PermissionEngine(get_db_session())
scope_id = kwargs.get("tenant_id") or kwargs.get("kb_id")
if not await engine.check_permission(user.id, resource_type, action, scope_id):
raise HTTPException(403, "Permission denied")
return await func(*args, **kwargs)
return wrapper
return decoratorPython
5.2 租户上下文中间件
class TenantContextMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
if any(request.url.path.startswith(p) for p in EXEMPT_PATHS):
return await call_next(request)
user = getattr(request.state, "user", None)
if not user:
return JSONResponse({"code": 401, "message": "Unauthorized"}, 401)
tenant_id = request.headers.get("X-Tenant-ID")
if not tenant_id:
tenant_id = self._resolve_default_tenant(user.id)
if not await self._validate_tenant_membership(user.id, tenant_id):
return JSONResponse({"code": 403, "message": "Not a member"}, 403)
request.state.tenant_id = tenant_id
request.state.org_id = await self._resolve_org_id(tenant_id)
request.state.user_group_id = await self._resolve_user_group_id(tenant_id)
return await call_next(request)Python
5.3 用户限流模块
class RateLimiterMiddleware(BaseHTTPMiddleware):
def __init__(self, app, redis_client):
super().__init__(app)
self.redis = redis_client
async def _sliding_window_check(self, key, max_requests, window):
now = time.time()
pipe = self.redis.pipeline()
pipe.zremrangebyscore(key, 0, now - window)
pipe.zadd(key, {str(now): now})
pipe.zcard(key)
pipe.expire(key, window)
results = await pipe.execute()
return results[2] <= max_requestsPython
5.4 向量数据库租户分区策略
5.4.1 分区策略对比
| 策略 | 隔离性 | 性能 | 资源利用率 | 适用场景 | 推荐引擎 |
| 数据库级分区 | ★★★★★ | ★★★★★ | ★★☆ | 高安全法人(物理隔离) | Milvus / ES |
| Collection 级分区 | ★★★★ | ★★★★ | ★★★ | 中等规模多法人 | Milvus / Infinity |
| Partition Key 分区 | ★★★ | ★★★ | ★★★★★ | 大规模 SaaS | Milvus / ES |
| 元数据过滤 | ★★ | ★★ | ★★★★★ | 小规模/兼容模式 | ES / Infinity |
5.4.2 推荐方案:Collection 级分区 + Partition Key 混合策略
策略选择逻辑:
isolation_level == 'physical' → 数据库级分区(每法人独立索引)
org.team_count < 100 → Collection 级分区(每团队一 Collection)
其他 → Partition Key 分区(共享 Collection + tenant_id 分区键)
5.5 空间模型设计
┌─────────────────────────────────────────────────────┐
│ Tenant (团队) │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ Public Space (公共空间) │ │
│ │ - 所有团队成员自动可见 │ │
│ │ - 存放公告、通用知识库 │ │
│ │ - team_admin 可管理内容 │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ Shared Space (共享空间) │ │
│ │ - 指定成员/角色可见 │ │
│ │ - 存放项目组知识库、跨团队共享资源 │ │
│ │ - team_admin 授权管理 │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ Private Space (私有空间) │ │
│ │ - 仅创建者可见 │ │
│ │ - 个人知识库、草稿 │ │
│ └──────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
5.6 数据逻辑隔离实现
5.6.1 数据库行级安全(PostgreSQL RLS)
ALTER TABLE knowledgebase ENABLE ROW LEVEL SECURITY;
ALTER TABLE document ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation_policy ON knowledgebase
USING (tenant_id = current_setting('app.current_tenant'));
CREATE POLICY org_isolation_policy ON knowledgebase
USING (org_id = current_setting('app.current_org'));SQL
5.6.2 Redis Key 隔离
def redis_key(scope: str, scope_id: str, *parts) -> str:
return f"ragflow:{scope}:{scope_id}:{':'.join(parts)}"
# ragflow:tenant:abc123:session:xyz789
# ragflow:org:org001:config:llm_settings
# ragflow:user:uid001:token_usage:20260608Python
5.6.3 MinIO 对象存储隔离
class TenantStorage:
def get_bucket_name(self, org_id, tenant_id=None):
org_config = self._get_org_config(org_id)
if org_config.isolation_level == 'physical':
return f"ragflow-org-{org_id}"
else:
return f"ragflow-tenant-{tenant_id}"
def get_object_path(self, tenant_id, kb_id, doc_id, filename):
return f"{tenant_id}/{kb_id}/{doc_id}/{filename}"Python
6 API 设计
6.1 新增 API 端点
| 模块 | 方法 | 路径 | 说明 |
| 法人管理 | POST | /api/v1/organizations | 创建法人 |
| GET | /api/v1/organizations | 列出法人 |
| GET | /api/v1/organizations/{org_id} | 获取法人详情 |
| PUT | /api/v1/organizations/{org_id} | 更新法人 |
| DELETE | /api/v1/organizations/{org_id} | 删除法人 |
| 团队管理 | POST | /api/v1/teams | 创建团队 |
| POST | /api/v1/teams/{id}/members | 邀请成员 |
| PUT | /api/v1/teams/{id}/members/{uid} | 修改成员角色 |
| DELETE | /api/v1/teams/{id}/members/{uid} | 移除成员 |
| 角色权限 | POST | /api/v1/teams/{id}/roles | 创建自定义角色 |
| PUT | /api/v1/teams/{id}/roles/{rid} | 更新角色权限 |
| POST | /api/v1/teams/{id}/members/{uid}/roles | 分配角色 |
| 空间管理 | POST | /api/v1/teams/{id}/spaces | 创建空间 |
| GET | /api/v1/teams/{id}/spaces | 列出空间 |
| POST | /api/v1/teams/{id}/spaces/{sid}/members | 添加空间成员 |
| 限流管理 | POST | /api/v1/rate-limits | 创建限流规则 |
| GET | /api/v1/rate-limits | 查询限流规则 |
| PUT | /api/v1/rate-limits/{id} | 修改限流规则 |
| GET | /api/v1/rate-limits/usage | 查询当前用量 |
| 文档管理 | GET | /api/v1/admin/documents | 全局文档列表 |
| PUT | /api/v1/admin/documents/{id}/status | 修改文档状态 |
| DELETE | /api/v1/admin/documents/{id} | 删除文档 |
6.2 现有 API 兼容性
| 现有 API | 变更 |
POST /api/v1/dataset | 新增可选字段 org_id, user_group_id, space_id |
GET /api/v1/dataset | 响应新增 org_id, user_group_id, space_id 字段 |
POST /api/v1/user/register | 自动创建默认法人+用户组+团队 |
| 所有需要 tenant_id 的 API | 支持从 X-Tenant-ID Header 或 JWT 中获取 |
7 前端改造要点
| 页面 | 路由 | 功能 |
| 法人管理 | /admin/organizations | 法人 CRUD、隔离级别配置 |
| 用户组管理 | /admin/groups | 用户组 CRUD、成员管理 |
| 团队管理增强 | /teams/{id} | 成员管理 + 角色分配 + 知识库管理 |
| 角色权限配置 | /teams/{id}/roles | 自定义角色、权限矩阵配置 |
| 空间管理 | /teams/{id}/spaces | 空间 CRUD、成员授权 |
| 限流配置 | /admin/rate-limits | 限流规则 CRUD、用量监控 |
| 系统文档管理 | /admin/documents | 全局文档管理、跨租户视图 |
8 数据迁移方案
8.1 迁移步骤
Phase 1: Schema 扩展(零停机)
- 新增 organization, user_group, org_user, user_group_member 等表
- 扩展 tenant 表(新增 org_id, user_group_id, tenant_type, space_config)
- 扩展 usertenant 表(role 字段扩展)
- 扩展 knowledgebase 表(新增 space_id, org_id, user_group_id)
- 新增 permission, role, role_permission, user_role, rate_limit_quota, space 表
Phase 2: 数据回填
- 为每个现有 tenant 创建默认 organization
- 为每个现有 tenant 创建默认 user_group
- 回填 tenant.org_id, tenant.user_group_id
- 回填 knowledgebase.org_id, knowledgebase.user_group_id
- 为现有 owner 角色映射为 team_admin
- 为现有知识库创建对应空间
Phase 3: 向量数据迁移
- 为现有 ES 索引添加 tenant_id, org_id 字段
- 按需重建索引(物理隔离租户)
- 验证查询结果一致性
Phase 4: 功能切换
- 部署新版本代码
- 启用 TenantContextMiddleware
- 启用 RateLimiterMiddleware
- 灰度开放新功能
8.2 回填 SQL 示例
-- Step 1: 为每个现有 tenant 创建默认法人
INSERT INTO organization (id, name, code, status, isolation_level, created_by)
SELECT id, CONCAT(name, '_org'), CONCAT('org_', id), '1', 'logical', id
FROM tenant;
-- Step 2: 为每个现有 tenant 创建默认用户组
INSERT INTO user_group (id, org_id, name, code, status, created_by)
SELECT id, id, CONCAT(name, '_group'), CONCAT('group_', id), '1', id
FROM tenant;
-- Step 3: 回填 tenant 扩展字段
UPDATE tenant t SET org_id = t.id, user_group_id = t.id, tenant_type = 'team';
-- Step 4: 回填 knowledgebase 扩展字段
UPDATE knowledgebase kb
JOIN tenant t ON kb.tenant_id = t.id
SET kb.org_id = t.org_id, kb.user_group_id = t.user_group_id;
-- Step 5: 为现有 owner 角色升级为 team_admin
UPDATE usertenant SET role = 'team_admin' WHERE role = 'owner';SQL
9 可复用性设计
9.1 中间件抽象
┌─────────────────────────────────────────────┐
│ Reusable Middleware Stack │
│ │
│ ┌─────────────────────────────────────┐ │
│ │ TenantContextMiddleware │ │
│ │ - JWT/OAuth 解析 │ │
│ │ - 租户上下文注入 │ │
│ │ - 多法人路由 │ │
│ └─────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────┐ │
│ │ PermissionEngine │ │
│ │ - RBAC 角色权限矩阵 │ │
│ │ - ABAC 属性策略 │ │
│ │ - @require_permission 装饰器 │ │
│ └─────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────┐ │
│ │ RateLimiterMiddleware │ │
│ │ - Redis 滑动窗口 │ │
│ │ - 多级配额(用户/团队/法人) │ │
│ │ - 可配置 API 路径模式 │ │
│ └─────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────┐ │
│ │ TenantDataAccessLayer │ │
│ │ - 自动注入 tenant_id 过滤 │ │
│ │ - 向量库分区路由 │ │
│ │ - 存储桶隔离 │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
9.2 配置驱动
tenant:
default_isolation_level: logical
auto_create_org_on_register: true
auto_create_group_on_register: true
max_teams_per_org: 100
max_members_per_team: 500
vector_db:
partition_strategy: collection
auto_create_partition: true
index_refresh_interval: 5s
rate_limit:
enabled: true
default_window: 60
default_max_requests: 100
storage_quota_default_mb: 5120YAML
10 安全增强
10.1 认证体系
| 认证方式 | 适用场景 |
| JWT (access_token + refresh_token) | 标准登录 |
| API Token | 服务间调用 |
| OAuth2 / OIDC | 企业 SSO 集成 |
| X-Tenant-ID Header | 多租户切换 |
10.2 安全措施清单
| 措施 | 描述 |
| TLS 1.3 | 全链路加密传输 |
| AES-256 静态加密 | 敏感数据加密存储 |
| JWT 签名校验 | 防止 token 伪造 |
| user_id 防伪造 | v0.25.6 已修复 session user_id spoofing |
| SSRF 防护 | v0.25.6 已修复 OAuth avatar SSRF |
| 敏感字段脱敏 | v0.25.6 已修复 API 响应泄露 |
| 审计日志 | 所有敏感操作记录不可篡改日志 |
| RBAC + ABAC | 细粒度权限控制 |
| 限流 | 防止 API 滥用 |
11 实施路线图
Phase 1 — 基础架构
- 数据模型扩展(新增表 + 扩展现有表)
- TenantContextMiddleware 实现
- 角色体系扩展(team_admin 角色)
- 数据迁移脚本
Phase 2 — 权限与限流
- PermissionEngine 实现
- RBAC 权限矩阵配置
- RateLimiterMiddleware 实现
- 限流配额管理 API
- 前端角色权限管理页面
Phase 3 — 多法人隔离
- Organization / UserGroup 管理 API
- 法人间数据逻辑隔离
- 向量数据库分区策略实现
- MinIO 存储桶隔离
- Redis Key 前缀隔离
Phase 4 — 空间模型
- Space 模型实现
- 公共/共享/私有空间管理
- 空间访问控制
- 系统管理员文档管理
Phase 5 — 测试与上线
- 集成测试
- 性能测试(多租户并发)
- 安全审计
- 灰度发布
- 全量上线
12 关键风险与应对
| 风险 | 影响 | 应对措施 |
| 高 向量库分区迁移数据量大 | 迁移时间长、可能影响在线服务 | 增量迁移 + 双写 + 灰度切换 |
| 中 权限引擎性能开销 | 每次 API 请求增加权限校验延迟 | 权限缓存(Redis TTL)+ 批量预加载 |
| 高 多法人隔离不彻底 | 数据泄露风险 | 自动化隔离测试 + 定期安全审计 |
| 中 限流误杀 | 正常用户被限流 | 限流规则灰度 + 白名单机制 + 监控告警 |
| 中 前端改造范围大 | 开发周期长 | 分阶段交付,优先核心功能 |
附录 A:RAGFlow v0.25.6 关键特性参考
| 特性 | 版本 | 与本方案关系 |
| 多 Admin 账户支持 | v0.24.0 | 基础:system_admin 角色已部分支持 |
| Admin UI | v0.22.0 | 基础:可扩展为法人/用户组管理界面 |
| 元数据过滤 (Tag Sets) | v0.22.0+ | 复用:向量库逻辑隔离可基于元数据过滤 |
| OAuth2/OIDC 集成 | v0.19.1 | 基础:企业 SSO 已支持 |
| SSRF/用户伪造修复 | v0.25.6 | 基础:安全加固已到位 |
附录 B:向量数据库选型建议
| 场景 | 推荐引擎 | 分区策略 |
| < 10 个法人,< 100 万文档 | Elasticsearch | 索引级分区(每法人一索引) |
| 10-100 个法人,100 万-1000 万文档 | Milvus | Collection 级分区(每团队一 Collection) |
| > 100 个法人,> 1000 万文档 | Milvus | Partition Key 分区(共享 Collection + tenant_id) |
| 高安全场景(金融/政务) | Milvus | 数据库级分区(每法人独立 Database) |
| 轻量级部署 | Infinity | 元数据过滤(逻辑隔离) |