Dify账户体系:多租户 + 多登录方式 + 权限模型全揭底
本文系统梳理Dify账户体系的核心架构,包括多租户设计、权限模型、SSO对接第三方系统的实现思路与安全细节,适合Dify二次开发、企业级集成与安全合规需求。
实体关系模型
dify的账户系统,直接看 api/models/account.py 就行了,里面包含了相关的实体
我们看下每个实体的作用:
- • Account:Dify的系统用户,包含基本信息和权限判断方法
- • Tenant:在Dify中叫workspace(工作空间),支持多租户架构
- • TenantAccountJoin:表示账户与租户的关联关系,定义角色权限
- • AccountIntegrate:表示第三方登录集成,支持OAuth等外部认证
- • InvitationCode:表示邀请加入租户的邀请码和邀请记录
- • TenantPluginPermission:表示租户内插件的权限设置
看这些模型就知道了,Dify这个账户体系还是挺复杂的。
角色这块分了OWNER/ADMIN/EDITOR/NORMAL/DATASET_OPERATOR这些,DATASET_OPERATOR这个角色还挺有意思。账户状态有PENDING(待激活)ACTIVE(正常)BANNED(封号)这些。
OAuth第三方登录也支持,通过AccountIntegrate这个表。邀请机制用InvitationCode,应该就是邀请码功能把
具体怎么流转的,得结合前端页面操作才能看明白。
账户管理
账户管理这块,主要看这几个文件:
- • oauth.py: OAuth第三方登录(GitHub/Google)那套
- • login.py: 普通登录、登出、密码重置
- • account.py: 账户模型和状态定义
- • account_service.py: 账户业务逻辑实现
用户注册是否允许注册注册失败创建账户发送邮件验证用户激活是否允许创建工作空间自动创建工作空间等待邀请加入设置为Owner角色等待管理员分配角色注册完成
基本逻辑是这样:
先检查系统让不让注册( FeatureService.get_system_features().is_allow_register
这个方法),能注册就创建账户,有邮件功能的话会发验证邮件。接下来看系统配置决定要不要自动建工作空间,不让建的话用户就的等管理员邀请了
** 登录流程 ** :
登录这块涉及好几个组件,画了个时序图
Redis缓存数据库TenantServiceAccountService控制器用户Redis缓存数据库TenantServiceAccountService控制器用户普通登录流程POST /login (email, password)authenticate(email, password)查询用户账户返回账户信息验证密码get_join_tenants(account)查询用户租户返回租户列表生成JWT Token存储Refresh Token返回TokenPair登录成功,返回Token
先验证邮箱密码,验证通过了就获取用户工作空间列表,接着生成JWT token和refresh token,最后把refresh token存Redis里。
源码里支持好几种登录方式:
# 来源:controllers/console/auth/login.py LoginApi.post() 方法
def post(self):
# 检查是否启用LDAP(这块代码是我加的)
if is_ldap_enabled():
account = AccountService.authenticate_ldap(args["email"], args["password"])
elif invitation:
# 邀请注册登录
account = AccountService.authenticate(args["email"], args["password"], args["invite_token"])
else:
# 普通登录
account = AccountService.authenticate(args["email"], args["password"])
** 邮箱验证码登录 ** :
还有个邮箱验证码登录,不用密码那种,对企业用户来说挺方便的:
# 来源:controllers/console/auth/login.py EmailCodeLoginSendEmailApi.post() 方法
# 发送验证码
token = AccountService.send_email_code_login_email(email=args["email"], language=language)
# 来源:controllers/console/auth/login.py EmailCodeLoginApi.post() 方法
# 验证码登录
token_data = AccountService.get_email_code_login_data(args["token"])
if token_data["code"] == args["code"]:
# 登录成功,创建或获取账户
account = AccountService.get_user_through_email(user_email)
第三方登录
OAuth第三方登录也支持,主要是GitHub和Google。流程图如下:
AccountServiceOAuth提供商Dify后端Dify前端用户AccountServiceOAuth提供商Dify后端Dify前端用户点击第三方登录GET /oauth/login/github重定向到GitHub授权页显示授权页面用户授权回调并返回授权码用exchange授权码获取access_token返回access_token使用token获取用户信息返回用户信息创建或关联本地账户返回账户信息重定向到前端并携带token登录成功
