从零开始学 Dify- 帐户与租户管理系统设计揭秘

Posted by Yezhiwei on May 8, 2025

本介绍了 Dify 的帐户和租户管理系统,该系统负责处理平台内的用户身份验证、工作区(租户)管理和用户权限。提供了全面的用户身份管理、多工作区支持以及基于角色的访问控制。

系统概述

帐户和租户管理系统是 Dify 的核心组件,用于管理:

  1. 用户帐户(User Accounts) ——注册、身份验证、配置文件管理
  2. 工作区(租户) - 拥有自己的成员和资源的组织单位
  3. 成员资格和角色 - 工作区内基于角色的访问控制
  4. 身份验证流程 - 多种身份验证方法,包括密码、电子邮件代码和 OAuth

架构图

数据模型

该系统围绕以下主要实体构建:

帐户管理

帐户创建和注册

Dify 支持多种创建账户的路径:

  1. 标准注册 - 电子邮件/密码注册
  2. 基于 OAuth 的注册 - 通过 GitHub 或 Google 注册
  3. 基于邀请的注册 - 受邀加入工作区
  4. 初始设置 - 系统设置期间的第一个用户

帐户创建主要由 AccountService 和 RegisterService 类处理。create_account 处理核心帐户创建逻辑,包括密码哈希和默认设置。

身份验证方法

Dify 支持多种身份验证方法:

  1. 基于密码的登录 - 传统的用户名/密码
  2. 电子邮件代码登录 - 一次性代码发送至电子邮件
  3. OAuth 提供商 - GitHub 和 Google 集成
  4. 基于令牌的身份验证 - 用于 API 访问的 JWT 令牌

身份验证由 AccountService 类管理,每种身份验证方法都有专门的方法:

密码验证:

account = AccountService.authenticate(email, password) 
token_pair = AccountService.login(account=account, ip_address=ip_address)

JWT 令牌管理:

access_token = AccountService.get_account_jwt_token(account) 
refresh_token = _generate_refresh_token() AccountService._store_refresh_token(refresh_token, account.id)

帐户安全功能

该系统实现了多项安全功能:

  1. 密码哈希 - 使用加盐密码哈希
  2. 速率限制 ——限制登录尝试和密码重置请求
  3. 基于 IP 的限制 - 限制通过 IP 发送电子邮件
  4. 令牌过期 - JWT 令牌在配置的时间后过期
  5. 刷新令牌轮换 - 刷新时使用新令牌以确保安全

租户(工作区)管理

Dify 中的租户代表包含应用程序、数据集和模型提供程序等资源的工作区。一个用户可以属于多个具有不同角色的租户,但同一时间只能有一个活跃租户。

租户创建

创建租户:

  1. 创建帐户时自动执行(默认工作区)
  2. 由具有适当权限的用户手动

TenantService 类负责处理租户的创建和管理:

tenant = TenantService.create_tenant(name) 
TenantService.create_tenant_member(tenant, account, role="owner")

创建租户时,它会生成一个 RSA 密钥对以用于安全操作:

tenant.encrypt_public_key = generate_key_pair(tenant.id)

基于角色的访问控制(Role-Based Access Control)

Dify 通过 TenantAccountJoin 表在租户内部实现基于角色的访问控制,该表定义了帐户和租户之间的关系。每个连接都关联一个角色:

  • 所有者(Owner) - 完全管理控制
  • 管理员(Admin) - 可以管理大多数资源,但不能删除工作区
  • 普通用户(Normal) - 具有有限权限的普通用户
  • 数据集操作员(Dataset Operator) - 数据集管理的特殊角色

租户切换

用户可以属于多个租户并在它们之间切换。系统会跟踪每个用户的当前活动租户:

TenantService.switch_tenant(account, tenant_id)

当用户登录时,系统会加载其当前租户:

current_tenant = TenantAccountJoin.query.filter_by(account_id=account.id, current=True).first() 
if current_tenant: 
	account.current_tenant_id = current_tenant.tenant_id

成员管理

邀请成员

工作区管理员可以邀请新成员加入租户。邀请流程包括:

  1. 生成邀请令牌
  2. 发送带有令牌的电子邮件
  3. 如果用户不存在则创建待处理帐户
  4. 接受邀请后分配角色

管理成员角色

工作区管理员可以更新现有成员的角色:

TenantService.update_member_role(tenant, member, new_role, operator)

更改所有者角色时,系统会确保始终只有一个所有者:

if new_role == "owner": 
	# Find the current owner and change their role to 'admin' 
	current_owner_join = TenantAccountJoin.query.filter_by(tenant_id=tenant.id, role="owner").first() current_owner_join.role = "admin"

移除成员

工作区管理员可以从租户中删除成员:

TenantService.remove_member_from_tenant(tenant, account, operator)

系统在允许删除成员之前会检查权限:

TenantService.check_member_permission(tenant, operator, account, "remove")

身份验证流程

登录流程

身份验证流程

密码重置流程

安全注意事项

速率限制

系统实施速率限制以防止滥用:

  1. 登录尝试(Login attempts) - 限制错误密码尝试次数
  2. 密码重置(Password reset) - 限制密码重置电子邮件
  3. 邮箱验证码登录(Email code login) - 限制验证码邮箱
  4. 基于 IP 的限制(IP-based limits) - 通过 IP 地址限制电子邮件发送
reset_password_rate_limiter = RateLimiter(prefix="reset_password_rate_limit", max_attempts=1, time_window=60 * 1) 
email_code_login_rate_limiter = RateLimiter(prefix="email_code_login_rate_limit", max_attempts=1, time_window=60 * 1) 
LOGIN_MAX_ERROR_LIMITS = 5 FORGOT_PASSWORD_MAX_ERROR_LIMITS = 5

Token 管理

系统使用两种类型的令牌:

  1. 访问令牌(Access tokens) - 用于 API 身份验证的短期 JWT 令牌
  2. 刷新令牌(Refresh tokens) - 存储在 Redis 中的长期令牌,用于获取新的访问令牌
REFRESH_TOKEN_PREFIX = "refresh_token:" 
ACCOUNT_REFRESH_TOKEN_PREFIX = "account_refresh_token:" 
REFRESH_TOKEN_EXPIRY = timedelta(days=dify_config.REFRESH_TOKEN_EXPIRE_DAYS)

删除帐户

Dify 支持通过验证流程删除帐户:

  1. 用户请求删除帐户
  2. 系统通过电子邮件发送验证码
  3. 用户通过验证码确认
  4. 帐户正在等待删除
# Generate verification 
code code = "".join([str(random.randint(0, 9)) for _ in range(6)]) 
token = TokenManager.generate_token(account=account, token_type="account_deletion", additional_data={"code": code}) 
# Delete account 
delete_account_task.delay(account.id)

与其他系统集成

帐户和租户管理系统与 Dify 的其他各种组件集成:

  1. 模型提供者系统(Model Provider System) - 使用租户上下文进行 API 密钥管理
  2. RAG 知识系统(RAG Knowledge System) - 根据租户成员资格控制对数据集的访问
  3. 对话系统(Conversation System) - 将对话与用户和租户关联起来
  4. 工作流系统(Workflow System) - 根据租户角色强制执行权限

总结

详细介绍了 Dify 的帐户和租户管理系统,该系统负责处理平台内的用户身份验证、工作区(租户)管理和用户权限。提供了全面的用户身份管理、多工作区支持以及基于角色的访问控制。

同时确保与其他系统集成时,Dify 内的所有资源都由租户正确隔离,并且在整个应用程序中实施适当的访问控制。

接下来将分别介绍各个子系统:

模型提供者系统(Model Provider System)

RAG 知识系统(RAG Knowledge System) 

对话系统(Conversation System) 

工作流系统(Workflow System) 

推荐阅读

参考资料

https://github.com/langgenius/dify

欢迎关注公众号,更及时的接收消息,后续会继续写一些相关 LLM 的文章。