agentic_huge_data_base / wiki
页面 Dify · 8.5 账号生命周期管理·DeepWiki 中文全文译文

8.5 · 账号生命周期管理(Account Lifecycle Management)

应用编排与外部知识接入 · 本章是 Dify DeepWiki 中文译文的独立章节页,保留原始链接、源码锚点、模块标签和章节层级。

项目Dify 章节8.5 状态全文译文 模块界面与交互、认证、权限与安全、系统架构、模型调用与提供方适配
源码线索
  • api/controllers/console/app/error.py
  • api/controllers/console/auth/data_source_oauth.py
  • api/controllers/console/auth/email_register.py
  • api/controllers/console/auth/error.py
  • api/controllers/console/auth/forgot_password.py
  • api/controllers/console/auth/login.py
  • api/controllers/console/auth/oauth.py
  • api/controllers/console/explore/error.py
  • api/controllers/console/explore/installed_app.py
  • api/controllers/console/feature.py
模块标签
  • 界面与交互
  • 认证、权限与安全
  • 系统架构
  • 模型调用与提供方适配
  • 接口与服务契约

中文译文

账号生命周期管理(中文译文)

原始 DeepWiki 页面:https://deepwiki.com/langgenius/dify/8.5-account-lifecycle-management
翻译时间:2026-05-27T08:44:34.846Z
翻译模型:deepseek-chat
原文字符数:16568
项目:Dify (dify)

---

账户生命周期管理

相关源文件

以下文件用于生成此维基页面:

  • api/controllers/console/app/error.py
  • api/controllers/console/auth/data_source_oauth.py
  • api/controllers/console/auth/email_register.py
  • api/controllers/console/auth/error.py
  • api/controllers/console/auth/forgot_password.py
  • api/controllers/console/auth/login.py
  • api/controllers/console/auth/oauth.py
  • api/controllers/console/explore/error.py
  • api/controllers/console/explore/installed_app.py
  • api/controllers/console/feature.py
  • api/controllers/console/workspace/account.py
  • api/controllers/console/workspace/members.py
  • api/controllers/console/workspace/model_providers.py
  • api/controllers/console/workspace/models.py
  • api/controllers/console/workspace/plugin.py
  • api/controllers/console/workspace/workspace.py
  • api/controllers/web/error.py
  • api/core/errors/error.py
  • api/extensions/ext_mail.py
  • api/libs/oauth.py
  • api/libs/oauth_data_source.py
  • api/libs/smtp.py
  • api/migrations/versions/2026_01_17_1110-f9f6d18a37f9_add_table_explore_banner_and_trial.py
  • api/schedule/mail_clean_document_notify_task.py
  • api/services/__init__.py
  • api/services/account_service.py
  • api/services/errors/__init__.py
  • api/services/errors/base.py
  • api/services/errors/enterprise.py
  • api/services/errors/llm.py
  • api/templates/change_mail_confirm_old_template_zh-CN.html
  • api/templates/transfer_workspace_owner_confirm_template_en-US.html
  • api/templates/without-brand/transfer_workspace_owner_confirm_template_en-US.html
  • api/tests/test_containers_integration_tests/services/test_feature_service.py
  • api/tests/unit_tests/libs/test_oauth_clients.py
  • api/tests/unit_tests/services/test_account_service.py
  • web/app/components/header/account-setting/members-page/__tests__/index.spec.tsx
  • web/app/components/header/account-setting/members-page/index.tsx
  • web/app/components/header/account-setting/members-page/operation/__tests__/index.spec.tsx
  • web/app/components/header/account-setting/members-page/operation/index.tsx

本文档描述了 Dify 中用户账户的完整生命周期,从创建到删除。内容涵盖账户注册、激活、认证令牌管理、密码重置流程、邮箱验证以及账户删除。

关于工作空间成员资格和角色的信息,请参见工作空间与成员管理。关于认证方法和会话管理,请参见认证方法与流程。关于多租户数据隔离,请参见租户模型与资源隔离

概述

账户生命周期管理主要由 AccountServiceRegisterService 类实现,并辅以令牌管理、速率限制和邮件发送等支持功能。系统支持多种账户创建路径(邮箱/密码、OAuth、基于邀请),并实现了全面的安全措施,包括速率限制、两阶段验证令牌以及带有冻结期的软删除。

来源: api/services/account_service.py:114-140, api/services/account_service.py:239-289

账户状态与转换

stateDiagram-v2
    [*] --> 待激活: RegisterService.register()
    待激活 --> 活跃: AccountInitApi.post()
    待激活 --> 封禁: 管理员操作
    活跃 --> 封禁: 管理员操作
    活跃 --> 已关闭: AccountService.delete_account()
    封禁 --> [*]
    已关闭 --> [*]

    note right of 待激活
        AccountStatus.PENDING
        未设置 initialized_at
    end note

    note right of 活跃
        AccountStatus.ACTIVE
        已设置 initialized_at 时间戳
    end note

    note right of 封禁
        AccountStatus.BANNED
        Unauthorized("账户已被封禁")
    end note

    note right of 已关闭
        AccountStatus.CLOSED
        软删除 / 计费冻结
    end note

来源: api/services/account_service.py:161-194, api/models/account.py:37-46, api/controllers/console/workspace/account.py:250-251

Account 模型使用 AccountStatus 枚举,包含四种状态:

  • 待激活(PENDING):账户已创建但尚未激活(未设置 initialized_at)。api/models/account.py:40
  • 活跃(ACTIVE):账户已完全初始化并可正常使用。api/models/account.py:40
  • 封禁(BANNED):账户被阻止认证;load_user 会抛出 Unauthorized 异常。api/services/account_service.py:166-168
  • 已关闭(CLOSED):账户被软删除,进入计费冻结期。api/models/account.py:40

账户创建流程

邮箱/密码注册

注册由 RegisterService.register() 处理,该方法会校验密码强度、使用唯一盐值进行哈希处理,并创建基础的 Account 及其初始 Tenant

sequenceDiagram
    participant 客户端
    participant RS [RegisterService]
    participant AS [AccountService]
    participant FS [FeatureService]
    participant BS [BillingService]
    participant DB [SQLAlchemy 会话]
    participant 邮件任务

    客户端->>RS: register(email, name, password)
    RS->>FS: get_system_features().is_allow_register
    FS-->>RS: 允许/拒绝

    alt 注册已禁用
        RS-->>客户端: AccountRegisterError
    end

    RS->>BS: is_email_in_freeze(email)
    BS-->>RS: 冻结状态

    alt 邮箱已冻结
        RS-->>客户端: AccountRegisterError
    end

    RS->>AS: create_account(email, name, password)
    AS->>AS: valid_password(password)
    AS->>AS: hash_password(password, salt)
    AS->>DB: add(Account)
    DB-->>AS: account 对象
    AS-->>RS: account

    RS->>RS: create_owner_tenant_if_not_exist(account)
    RS->>DB: add(Tenant), add(TenantAccountJoin)

    RS->>邮件任务: send_email_register_mail_task.delay()

    RS-->>客户端: account

来源: api/services/account_service.py:507-539, api/libs/password.py:11-34, api/controllers/console/auth/email_register.py:53-111

关键实现细节:

  • 通过 valid_password() 进行密码校验。api/libs/password.py:11-16
  • 使用 secrets.token_bytes(16) 生成盐值。api/libs/password.py:21
  • 使用 hash_password() 进行密码哈希,该函数采用 hashlib.pbkdf2_hmac 算法,迭代次数为 100,000 次。api/libs/password.py:19-31
  • 哈希结果以 base64 编码字符串形式存储在 Account.passwordAccount.password_salt 字段中。api/models/account.py:116-117
OAuth 注册

OAuth 注册通过 open_idemail 解析账户。如果账户不存在,则会生成新账户并关联集成信息。

graph TB
    subgraph "OAuth 控制器"
        OAuthLogin["OAuthLogin.get()<br/>/console/api/oauth/login/{provider}"]
        OAuthCallback["OAuthCallback.get()<br/>/console/api/oauth/authorize/{provider}"]
    end

    subgraph "OAuth 提供商"
        GitHubOAuth["GitHubOAuth"]
        GoogleOAuth["GoogleOAuth"]
    end

    subgraph "账户解析"
        GetByOpenId["Account.get_by_openid(provider, id)"]
        GetByEmail["AccountService.get_account_by_email_with_case_fallback()"]
        GenerateAccount["_generate_account()"]
    end

    subgraph "持久化"
        RegisterService["RegisterService.register()"]
        LinkIntegrate["AccountService.link_account_integrate()"]
        CreateWorkspace["TenantService.create_owner_tenant_if_not_exist()"]
    end

    OAuthLogin --> GitHubOAuth
    OAuthLogin --> GoogleOAuth
    GitHubOAuth --> OAuthCallback
    GoogleOAuth --> OAuthCallback

    OAuthCallback --> GetByOpenId
    GetByOpenId -->|未找到| GetByEmail
    GetByEmail --> GenerateAccount

    GenerateAccount --> RegisterService
    RegisterService --> CreateWorkspace
    GenerateAccount --> LinkIntegrate

来源: api/controllers/console/auth/oauth.py:82-173, api/libs/oauth.py:15-101, api/services/account_service.py:780-802

OAuth 提供商通过环境变量 GITHUB_CLIENT_IDGOOGLE_CLIENT_ID 进行配置。api/controllers/console/auth/oauth.py:34-54 AccountIntegrate 模型存储与提供商 open_id 关联的 OAuth 链接信息。api/models/account.py:145-156

基于邀请的注册

邀请功能允许现有成员添加用户。如果用户不存在,则会创建一个 PENDING 状态的账户。

sequenceDiagram
    participant 邀请者
    participant RS [RegisterService]
    participant 被邀请者客户端
    participant 激活API
    participant DB [SQLAlchemy]

    邀请者->>RS: invite_new_member(tenant, email, role)

    alt 账户已存在
        RS->>DB: add(TenantAccountJoin)
        RS->>被邀请者客户端: send_invite_member_mail_task()
    else 账户不存在
        RS->>AS: create_account(email, name=email)
        RS->>DB: add(Account, status=PENDING)
        RS->>DB: add(TenantAccountJoin)
        RS->>RS: _generate_invite_token()
        RS->>Redis: SET account_invite:{token}
        RS->>被邀请者客户端: send_invite_member_mail_task()
    end

    被邀请者客户端->>激活API: POST /activate
    激活API->>RS: get_invitation_with_case_fallback(token)
    RS->>Redis: GET account_invite:{token}

    激活API->>DB: UPDATE Account (status=ACTIVE)
    激活API->>RS: revoke_token(token)

来源: api/services/account_service.py:1071-1235, api/controllers/console/workspace/members.py:99-168

邀请令牌存储在 Redis 中,有效期为 72 小时。api/services/account_service.py:1071-1075

账户激活

激活令牌校验

激活流程采用两步验证过程:

  1. 令牌检查GET /activate/check):通过 RegisterService.get_invitation_with_case_fallback() 校验令牌。为了向后兼容,该方法支持不区分大小写的邮箱匹配。api/controllers/console/auth/activate.py:46-88
  2. 账户激活POST /activate):校验令牌,将 Account 状态更新为 ACTIVE,设置 initialized_at,并配置用户偏好设置,如 interface_languagetimezoneapi/controllers/console/auth/activate.py:90-127
不区分大小写的邮箱处理

Dify 通过将输入统一转换为小写,同时使用原始字符串和规范化字符串搜索现有记录,从而保持与大小写不同账户的兼容性。

来源: api/services/account_service.py:780-792

密码管理

密码重置流程

密码重置采用两阶段令牌系统,以防止重放攻击并确保一次性授权。

sequenceDiagram
    participant 用户
    participant FP_API [ForgotPasswordAPI]
    participant AS [AccountService]
    participant TM [TokenManager]
    participant Redis

    用户->>FP_API: POST /forgot-password
    FP_API->>AS: send_reset_password_email()
    AS->>TM: generate_token(type="reset_password")
    TM->>Redis: SETEX password_reset:{token} (3600s)

    Note over 用户,Redis: 阶段 1:邮箱验证

    用户->>FP_API: POST /forgot-password/validity
    FP_API->>AS: get_reset_password_data(token)
    AS->>TM: get_token_data(token, "reset_password")

    FP_API->>AS: revoke_reset_password_token(old_token)
    FP_API->>AS: generate_reset_password_token(email, phase="reset")
    FP_API-->>用户: new_token (阶段 2)

    Note over 用户,Redis: 阶段 2:密码重置

    用户->>FP_API: POST /forgot-password/resets
    FP_API->>AS: get_reset_password_data(token)
    FP_API->>AS: revoke_reset_password_token(token)
    FP_API->>DB: UPDATE Account SET password

来源: api/controllers/console/auth/forgot_password.py:60-193, api/services/account_service.py:473-505

两阶段令牌系统
阶段令牌数据目的有效操作
验证{email, code}验证邮箱所有权validity 检查
重置{email, code, phase: "reset"}授权密码更改resets 更新

来源: api/controllers/console/auth/forgot_password.py:139-144, api/controllers/console/auth/forgot_password.py:168-173

令牌管理

访问令牌(JWT)

AccountService.get_account_jwt_token() 生成,访问令牌是由 PassportService 签名的 JWT。api/services/account_service.py:182-194

刷新令牌生命周期

刷新令牌是存储在 Redis 中的随机字符串,用于支持令牌撤销和会话管理。

sequenceDiagram
    participant 客户端
    participant LoginAPI
    participant AS [AccountService]
    participant Redis

    客户端->>LoginAPI: POST /login
    LoginAPI->>AS: login(account)
    AS->>AS: _generate_refresh_token()
    AS->>Redis: SETEX refresh_token:{token} account_id
    AS->>Redis: SETEX account_refresh_token:{account_id} token

    Note over 客户端,Redis: 令牌刷新

    客户端->>LoginAPI: POST /refresh-token
    LoginAPI->>AS: refresh_token(old_token)
    AS->>Redis: GET refresh_token:{old_token}
    AS->>Redis: DELETE old keys
    AS->>Redis: SETEX new keys

来源: api/services/account_service.py:426-467, api/services/account_service.py:141-160

账户删除

异步删除过程

账户删除是一个软删除过程,通过 Celery 异步处理。

  1. 验证:用户必须提供发送到其邮箱的验证码。api/controllers/console/workspace/account.py:401-432
  2. 企业同步:如果启用,sync_account_deletion() 会通知关联的工作空间。api/services/account_service.py:312-343
  3. 任务执行delete_account_task 将账户状态设置为 CLOSED,并在适用时启动 30 天的计费冻结期。api/tasks/delete_account_task.py:14-43

来源: api/services/account_service.py:345-358, api/tasks/delete_account_task.py:14-43

速率限制与安全

Dify 使用多个 RateLimiter 实例来保护敏感流程。

限流器名称最大尝试次数时间窗口键前缀
reset_password_rate_limiter160sreset_password_rate_limit
email_register_rate_limiter160semail_register_rate_limit
email_code_login_rate_limiter3300semail_code_login_rate_limit
change_email_rate_limiter160schange_email_rate_limit

来源: api/services/account_service.py:124-133, api/libs/helper.py:246-281

RateLimiter 类使用 Redis 的 setex 命令在指定时间窗口内跟踪尝试次数。api/libs/helper.py:270-281