首页
/ OpenViking 多租户架构实战:account/user 身份边界、认证模式与集成模式详解

OpenViking 多租户架构实战:account/user 身份边界、认证模式与集成模式详解

2026-09-09 21:19:12作者:宗隆裙

本文围绕 OpenViking 的多租户能力展开,讲解其"单实例服务多团队/多客户"的身份隔离模型、api_keytrusted 两种认证模式、存储层的自动 account 前缀机制,以及 OpenClaw 插件与 Vikingbot 两种典型集成实践的取舍。读完本文,你将掌握通过 root_api_key 启用正式多租户、使用 Admin API 管理账户与用户、为日常数据访问签发并轮换 user key,以及依据业务形态选择正确多租户模式的方法。

一、多租户是什么:不是"每团队一套独立服务器"

OpenViking 的多租户并不等同于"为每个团队部署一套相互隔离的服务器"。它的设计主张是:一个 OpenViking Server 进程,通过 accountuser 两级身份边界,来控制数据共享与隔离。这一模型恰好覆盖两类典型场景:

  • 多团队/多客户共享一套服务:不同团队或客户的数据必须互相隔离;
  • 团队内多用户:团队成员需要共享资源,但各自的记忆(memories)保持隔离。

启用多租户后,单个 Server 即可:

  • 同时服务多个团队、客户或应用;
  • account 隔离不同团队;
  • 在同一 account 内默认共享 resources,并可通过 ACL 做目录级/文件级授权;
  • user 隔离用户记忆与会话;
  • 以 ROOT / ADMIN / USER 三级角色管理权限;
  • 支持 OpenClaw 插件、Vikingbot、CLI、HTTP SDK 等多种集成形态。

二、核心身份模型:account / user / role

2.1 account_id:外层租户边界

account 可以理解为工作区(workspace)、团队或客户空间:

  • 不同 account 之间的数据默认完全隔离
  • 只有 ROOT 能创建和删除 account
  • resourcesusersession 都归属某个 account 内部。

从源码看,RequestContext 直接由 UserIdentifier(account_id, user_id) 构造,account_id 贯穿 Router → Service → VikingFS 全链路(见 openviking/server/identity.py),这正是"请求上下文"驱动隔离的实现基础。

2.2 user_id:账户内用户边界

  • 用户记忆、用户会话按 user_id 隔离;
  • 普通用户只能访问自己的用户空间;
  • account 内的 admin 可以管理用户。

2.3 三级角色

角色 作用域 典型能力
ROOT 全局 创建/删除 account、跨租户访问、用户管理
ADMIN 单个 account 管理同 account 内的用户、重新生成用户 key
USER 单个 account 访问自己的 user/peer/session 数据以及同 account 内共享资源

角色在 openviking/server/identity.py 中被定义为一个带权限等级(rank)的类型:USER=0ADMIN=1ROOT=2,同时支持 Role.register(name, rank) 动态注册自定义角色。

三、两种多租户认证模式

模式 配置 身份来源 典型场景
api_key server.auth_mode = "api_key" Root key 或 user key 标准部署
trusted server.auth_mode = "trusted" 上游注入的 X-OpenViking-Account / X-OpenViking-User 位于可信网关之后

trusted 模式下,上游网关还可以断言 X-OpenViking-Role: userX-OpenViking-Role: admin。角色断言要求配置了 root_api_key 且请求携带匹配的 API key;X-OpenViking-Role: root 会被拒绝——ROOT 保留给经过校验的 Admin API 回退路径。

3.1 root_api_key 的作用

一旦配置 server.root_api_key,OpenViking 即进入正式多租户模式

  • Root key 负责管理账户与用户;
  • User key 由 Admin API 生成,供普通数据访问使用;
  • 服务器从 user key 解析出 account_iduser_id 和角色。

反过来,若 auth_mode = "api_key"未配置 root_api_key,服务器运行在 dev 模式

  • 所有请求按 ROOT 处理;
  • 默认身份是 default/default
  • 仅允许在 localhost 上运行。

结合 docs/en/guides/04-authentication.md 的说明:如果 auth_mode 未显式配置,配置了非空 root_api_key 时自动选择 api_key 模式,否则自动选择 dev 模式;把 root_api_key 设为空字符串 "" 是非法配置。

四、共享与隔离边界

4.1 逻辑层

数据类型 跨 account 共享 account 内共享 默认隔离边界
共享资源(viking://resources 默认共享,ACL 可限制 account / ACL
用户资源(viking://user/{user_id}/resources user
Peer 资源(viking://user/{user_id}/peers/{peer_id}/resources user / peer
记忆(Memories) user / peer
技能(Skills) user
会话(Sessions) user / session

4.2 存储层:隐藏的 account 前缀

对用户而言,URI 看起来仍然是普通的 viking://... 路径:

viking://resources/project-a/
viking://user/alice/memories/
viking://user/alice/resources/
viking://user/alice/peers/web-visitor-alice/resources/

但底层存储会自动加上 account 前缀:

/local/{account_id}/resources/project-a/
/local/{account_id}/user/alice/memories/
/local/{account_id}/user/alice/resources/
/local/{account_id}/user/alice/peers/web-visitor-alice/resources/

所以多租户隔离并不依赖特殊的公共 URI 格式,而是依赖请求上下文中的 account_iduser_id,并贯穿整个技术栈一致地生效。例如在删除账户时,openviking/server/routers/admin.py 会级联清理 AGFS 数据(/local/{account_id} 目录)与 VectorDB 记录,最后才删除账户元数据。

4.3 文件系统与检索层

文件系统操作与语义检索都是租户感知(tenant-aware)的:

  • 非 ROOT 请求自动按 account_id 过滤;
  • resources 默认包含 account 共享资源,配置了 ACL 时使用有效 ACL;
  • 用户资源始终限定在当前用户空间;需要共享就把它们移到 viking://resources
  • memoryskill 仍按当前用户空间过滤;
  • actor peer 会在文件系统与检索操作中把 viking://user/{user}/peers 过滤到单个 peer。

这套机制保证了"能搜到的 = 能读到的"。

4.4 Peer 集合过滤(Peer Collection Filter)

peer_id 是当前用户边界内的内容作用域,它从不改变租户或用户身份。当请求只需要看到当前用户 peer 集合中的某一个 peer 时,可设置:

X-OpenViking-Actor-Peer: <peer_id>

(或通过 SDK/CLI 的 actor_peer_id 参数),其效果如下:

  • 空目标检索仍包含当前用户根目录与共享的 viking://resources
  • 当检索解析 viking://user/{user}/peers 时,只选中该 peer 的记忆/资源;
  • 文件系统操作无法对 viking://user/{user}/peers 下其他 peer 进行读取、list/tree、grep/find/search、写入、移动或删除;
  • 用户范围的记忆、资源、技能、共享资源与会话归属保持不变;
  • peer ID 必须是安全的单路径段,例如 web-visitor-alice

从实现上看,actor_peer_idRequestContext 的一个字段(openviking/server/identity.py),并广泛作用于命名空间解析与检索目标构建(见 openviking/core/namespace.pyopenviking/core/retrieval_targets.py)。

五、标准使用流程

步骤 1:启用多租户

{
  "server": {
    "auth_mode": "api_key",
    "root_api_key": "your-secret-root-key"
  }
}

步骤 2:ROOT 创建 account 与首个 admin

curl -X POST http://localhost:1933/api/v1/admin/accounts \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-secret-root-key" \
  -d '{
    "account_id": "acme",
    "admin_user_id": "alice"
  }'

响应中会携带 alice 的 user_key(Admin API 实现见 openviking/server/routers/admin.py)。

步骤 3:ADMIN 或 ROOT 注册普通用户

curl -X POST http://localhost:1933/api/v1/admin/accounts/acme/users \
  -H "Content-Type: application/json" \
  -H "X-API-Key: <admin-or-root-key>" \
  -d '{
    "user_id": "bob",
    "role": "user"
  }'

步骤 4:普通应用流量优先使用 user key

curl http://localhost:1933/api/v1/fs/ls?uri=viking:// \
  -H "X-API-Key: <bob-user-key>"

这样服务器可以直接从 key 解析身份,无需额外的租户头。

步骤 5:数据 API 身份来自 user/admin key

api_key 模式下,lsfindsessions 等租户范围数据 API 从 API key 本身解析有效的 account 与 user。此模式下不要发送 X-OpenViking-AccountX-OpenViking-User——基于 header 的身份断言属于 trusted 模式。

  • ADMIN key 可以以自身 account/user 调用数据 API(如 ls viking://);
  • ROOT key 只用于 Admin API 和少量系统/监控 API,因为它不绑定租户用户,在 api_key 模式下无法访问租户范围的数据 API。数据访问请用 user/admin key,或改用 trusted 模式做上游身份断言。

完整演练:Admin 工作流示例

仓库的 examples/multi_tenant 目录提供了一个端到端的完整示例,包含配置模板、Python SDK 脚本和 CLI 脚本,覆盖以下流程:

 1. Health Check              无需认证,验证服务可用
 2. Create Account            ROOT 创建 account "acme",同时创建首个 admin "alice"
 3. Register User (ROOT)      ROOT 在 "acme" 下注册普通用户 "bob"
 4. Register User (ADMIN)     alice (ADMIN) 在 "acme" 下注册用户 "charlie"
 5. List Accounts             ROOT 列出所有 account
 6. List Users                列出 "acme" 下所有用户及角色
 7. Change Role               ROOT 将 bob 提升为 ADMIN
 8. Regenerate Key            为 charlie 重新生成 key,旧 key 立即失效
 9. Access Data               bob 使用 user key 访问数据
10. Error Tests               非法 key、权限不足、重复创建、旧 key 等负面用例
11. Remove User               删除 charlie,验证其 key 失效
12. Delete Account            删除 account "acme",验证 alice 的 key 也失效

运行方式:

# Python SDK(依赖 uv)
uv sync
uv run admin_workflow.py --url http://localhost:1933 --root-key my-root-key

# CLI 脚本
ROOT_KEY=my-root-key SERVER=http://localhost:1933 bash admin_workflow.sh

服务端配置文件模板见 examples/multi_tenant/ov.conf.example,其中 server.root_api_key 即为启用多租户认证的关键项。注意该示例同时配置了 embedding 与 VLM 的 API Key,你需要填入自己的密钥。

六、Admin API 与 CLI 命令参考

6.1 Admin API 端点

方法 端点 所需角色 说明
POST /api/v1/admin/accounts ROOT 创建 account + 首个 admin
GET /api/v1/admin/accounts ROOT 列出所有 account
DELETE /api/v1/admin/accounts/{id} ROOT 删除 account(级联清理存储)
POST /api/v1/admin/accounts/{id}/users ROOT, ADMIN 注册用户
GET /api/v1/admin/accounts/{id}/users ROOT, ADMIN 列出用户
DELETE /api/v1/admin/accounts/{id}/users/{uid} ROOT, ADMIN 移除用户
PUT /api/v1/admin/accounts/{id}/users/{uid}/role ROOT 修改用户角色(源码中目前仅支持提升为 ADMIN,见 openviking/server/routers/admin.py
POST /api/v1/admin/accounts/{id}/users/{uid}/key ROOT, ADMIN 重新生成 user key(旧 key 立即失效)

6.2 CLI 命令

# Account 管理
openviking admin create-account <account_id> --admin <admin_user_id>
openviking admin list-accounts
openviking admin delete-account <account_id>

# User 管理
openviking admin register-user <account_id> <user_id> [--role user|admin]
openviking admin list-users <account_id>
openviking admin remove-user <account_id> <user_id>
openviking admin set-role <account_id> <user_id> <role>
openviking admin regenerate-key <account_id> <user_id>

此外,在 ovcli.conf 中同时配置 api_keyroot_api_key 后,可用 ov --sudo 执行管理命令:

{
  "url": "http://localhost:1933",
  "api_key": "<user-key>",
  "root_api_key": "<root-key>"
}
ov --sudo admin list-accounts
ov --sudo reindex viking://
ov --sudo system status

--sudo 仅对 adminsystemreindex 这类管理/系统命令生效,并且要求 ovcli.conf 中配置了 root_api_key

七、两种典型集成模式

7.1 OpenClaw 插件:一个实例持有一个 user key

当前 OpenClaw 插件遵循"插件持有单一用户身份"的模型:

  • 远程模式配置为 baseUrl + apiKey,可选 peer_role / peer_prefix
  • apiKey 通常应为 user key
  • 服务器从该 user key 解析 account_iduser_id
  • 插件把 OpenClaw agent 身份放在 peer/session 元数据中,而不是租户 header 中。

典型配置:

openclaw config set plugins.entries.openviking.config.mode remote
openclaw config set plugins.entries.openviking.config.baseUrl "http://your-server:1933"
openclaw config set plugins.entries.openviking.config.apiKey "<user-api-key>"
openclaw config set plugins.entries.openviking.config.peer_role assistant
openclaw config set plugins.entries.openviking.config.peer_prefix "<peer-prefix>"

该模型的特点:

  • 集成简单——插件不管理 account/user 生命周期;
  • 最适合"一个 OpenClaw 实例映射到一个 OpenViking 用户身份";
  • peer_prefix 用于构建 peer/session 元数据时区分不同 OpenClaw 运行时身份;
  • 同 account 内 resources 默认共享、可用 ACL 限制,用户记忆保持 user 级隔离。

为什么插件通常不设置 account / user:在 api_key 模式下 user key 已经足够表达身份——accountuser 由服务器端从 key 解析,插件只需用 peer_prefix 做运行时身份标注,内部写用户级记忆、用 peer_id 标识每条消息的发言者。如果直接把 root key 给插件,普通租户范围数据 API 将无法获得 key 绑定的租户用户,这不是日常访问的好默认值。

7.2 Vikingbot:root key 管理大量终端用户

Vikingbot 的做法不同——它更像一个服务大量终端用户的平台:

  • 机器人用 root key 连接 OpenViking;
  • 机器人配置中固定一个 account_id
  • 机器人自动在该 account 内注册用户;
  • 机器人缓存每个用户的 user key,并在记忆提交/搜索时尽可能使用 user key。

示例配置:

{
  "bot": {
    "ov_server": {
      "server_url": "http://127.0.0.1:1933",
      "root_api_key": "test",
      "account_id": "default",
      "admin_user_id": "default"
    }
  }
}

该模型的特点:

  • 适合一个 bot 服务服务大量聊天用户;
  • 同 account 内 resources 默认共享,ACL 可细化到具体目录或文件的访问;
  • 用户记忆通过自动管理的用户身份实现隔离;
  • 相比 OpenClaw 插件,bot 承担了更多租户生命周期管理逻辑。

7.3 如何选择

场景 推荐模式
一个 OpenClaw 实例映射到一个固定身份 OpenClaw 插件 + user key
一个网关或 bot 服务大量终端用户 Vikingbot + root-key 管理用户
可信网关在上游注入身份 trusted 模式
本地单用户体验、无需正式租户隔离 不配置 root_api_key 的 dev 模式

八、常见误区

1. root_api_key 不是日常业务访问 key

Root key 主要用于:创建/删除 account、注册用户、重新生成 key、运维与诊断。日常应用流量应根据调用者身份使用 user key 或 admin key。

2. peer_id 不定义租户

peer_id 标识当前用户下的某个交互 peer,它不创建租户,但可以通过显式 peer URI 或 peer 集合过滤来圈选 peer 内容,例如:

viking://user/{user_id}/peers/{peer_id}/memories
viking://user/{user_id}/peers/{peer_id}/resources

租户边界是 account_id,用户边界是 user_id,peer 内容始终停留在该用户边界之内。

3. 没有 root_api_key 不等于"正式的单租户生产模式"

那只是 dev 模式:所有请求以 ROOT 运行,不适合公开或共享部署。从 docs/en/guides/04-authentication.md 可知,dev 模式下服务器仅允许绑定 localhost,绑定到非回环地址(如 0.0.0.0)会拒绝启动。

4. OpenClaw 插件与 Vikingbot 不是同一种多租户模式

  • OpenClaw 插件 ≈ "客户端直接使用一个用户身份";
  • Vikingbot ≈ "平台管理大量用户及其 user key"。

九、延伸阅读

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
docsdocs
暂无描述
Markdown
899
5.83 K
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
925
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
601
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
395
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.04 K
525