agentic_huge_data_base / wiki
页面 Open WebUI · 11.3 LDAP 集成·DeepWiki 中文全文译文

11.3 · LDAP 集成(LDAP Integration)

多模型对话工作台与知识应用入口 · 本章是 Open WebUI DeepWiki 中文译文的独立章节页,保留原始链接、源码锚点、模块标签和章节层级。

项目Open WebUI 章节11.3 状态全文译文 模块认证、权限与安全、接口与服务契约、系统架构、工具、记忆与模型调用
源码线索
  • backend/open_webui/config.py
  • backend/open_webui/env.py
  • backend/open_webui/main.py
  • backend/open_webui/routers/auths.py
  • backend/open_webui/utils/auth.py
  • backend/open_webui/utils/oauth.py
  • backend/open_webui/models/groups.py
模块标签
  • 认证、权限与安全
  • 接口与服务契约
  • 系统架构
  • 工具、记忆与模型调用
  • 检索、召回与知识系统

中文译文

LDAP 集成(中文译文)

原始 DeepWiki 页面:https://deepwiki.com/open-webui/open-webui/11.3-ldap-integration
翻译时间:2026-06-09T16:10:42.075Z
翻译模型:deepseek-chat
原文字符数:14327
项目:Open WebUI (open-webui)

---

LDAP 集成

相关源文件

本 Wiki 页面基于以下文件生成:

  • backend/open_webui/config.py
  • backend/open_webui/env.py
  • backend/open_webui/main.py
  • backend/open_webui/routers/auths.py
  • backend/open_webui/utils/auth.py
  • backend/open_webui/utils/oauth.py

本文档介绍 Open WebUI 中的 LDAP(轻量级目录访问协议)认证集成,包括配置、认证流程、用户预置和组同步。关于基于 OAuth 的认证,请参见 OAuth 集成。关于通用认证概念和 JWT 令牌管理,请参见 认证方法。

概述

Open WebUI 支持 LDAP 认证,可与 Active Directory 或其他 LDAP 服务器集成。该集成允许用户使用目录凭据进行认证,在首次登录时自动预置用户,并可选择从 LDAP 目录同步组成员身份。

LDAP 实现使用 ldap3 Python 库,支持:

  • TLS/SSL 加密连接
  • 自定义证书验证
  • 灵活的属性映射
  • 用于用户访问控制的搜索过滤器
  • 自动用户预置
  • LDAP 组到 Open WebUI 组的同步
  • 自动组创建

架构

下图展示了前端登录表单、FastAPI 后端路由器和外部 LDAP 服务器之间的交互。

LDAP 认证架构

graph TB
    subgraph "客户端层"
        LoginForm["登录表单<br/>(邮箱/密码)"]
    end

    subgraph "认证路由器 [backend/open_webui/routers/auths.py]"
        LDAPEndpoint["/api/v1/auths/ldap<br/>ldap_auth()"]
        LDAPForm["LdapForm<br/>{user, password}"]
    end

    subgraph "配置层"
        AppConfig["request.app.state.config<br/>LDAP 配置"]
        ConfigEndpoints["管理配置端点<br/>/admin/config/ldap/*"]
    end

    subgraph "LDAP 连接 [ldap3]"
        TlsConfig["Tls<br/>validate, version, ca_certs_file"]
        Server["ldap3.Server<br/>host, port, use_ssl"]
        AppConnection["connection_app<br/>LDAP_APP_DN 绑定"]
        UserConnection["connection_user<br/>用户 DN 绑定"]
    end

    subgraph "LDAP 操作"
        UserSearch["connection_app.search()<br/>按用户名查找用户"]
        AttributeExtract["提取属性<br/>email, cn, groups"]
        UserBind["connection_user.bind()<br/>认证用户"]
    end

    subgraph "本地数据库 [SQLAlchemy]"
        UsersDB["用户表<br/>用户记录"]
        AuthsDB["认证表<br/>认证数据"]
        GroupsDB["组表<br/>组成员身份"]
    end

    subgraph "用户预置"
        UserLookup["Users.get_user_by_email()"]
        UserCreate["Auths.insert_new_auth()"]
        GroupSync["Groups.sync_groups_by_group_names()"]
        GroupCreate["Groups.create_groups_by_group_names()"]
    end

    subgraph "会话管理"
        TokenCreate["create_token()"]
        CookieSet["response.set_cookie('token')"]
        SessionResponse["SessionUserResponse"]
    end

    LoginForm --> LDAPEndpoint
    LDAPEndpoint --> LDAPForm
    LDAPEndpoint --> AppConfig

    AppConfig --> TlsConfig
    AppConfig --> Server
    TlsConfig --> Server

    Server --> AppConnection
    AppConnection --> UserSearch
    UserSearch --> AttributeExtract

    AttributeExtract --> Server
    Server --> UserBind

    UserBind --> UserLookup
    UserLookup --> UserCreate
    UserCreate --> UsersDB
    UserCreate --> AuthsDB

    AttributeExtract --> GroupCreate
    GroupCreate --> GroupsDB
    GroupCreate --> GroupSync
    GroupSync --> GroupsDB

    UserLookup --> TokenCreate
    TokenCreate --> CookieSet
    CookieSet --> SessionResponse

    ConfigEndpoints --> AppConfig

来源:backend/open_webui/routers/auths.py:231-500, backend/open_webui/routers/auths.py:1055-1140

配置

LDAP 服务器配置

LDAP 服务器设置通过应用的动态配置系统管理,可通过环境变量或管理设置界面修改。

配置参数类型描述默认值
ENABLE_LDAPbool启用/禁用 LDAP 认证的主开关false
LDAP_SERVER_LABELstringLDAP 服务器的显示名称必填
LDAP_SERVER_HOSTstringLDAP 服务器主机名或 IP 地址必填
LDAP_SERVER_PORTintLDAP 服务器端口389(明文),636(TLS)
LDAP_ATTRIBUTE_FOR_MAILstring包含电子邮件地址的 LDAP 属性"mail"
LDAP_ATTRIBUTE_FOR_USERNAMEstring包含用户名的 LDAP 属性"uid"
LDAP_APP_DNstring应用绑定的专有名称必填
LDAP_APP_PASSWORDstring应用 DN 的密码必填
LDAP_SEARCH_BASEstring用户搜索的基础 DN必填
LDAP_SEARCH_FILTERSstring用于限制访问的附加 LDAP 过滤器""
LDAP_USE_TLSbool启用 TLS/SSL 加密true
LDAP_CA_CERT_FILEstringCA 证书文件路径None
LDAP_VALIDATE_CERTbool验证服务器证书true
LDAP_CIPHERSstringTLS 密码套件规范"ALL"

来源:backend/open_webui/routers/auths.py:1039-1053, backend/open_webui/routers/auths.py:1055-1072, backend/open_webui/config.py:51-53

配置 API 端点

后端提供多个管理端点来管理 LDAP 设置:

  • GET /api/v1/auths/admin/config/ldap:返回当前的 ENABLE_LDAP 状态。backend/open_webui/routers/auths.py:1125-1128
  • POST /api/v1/auths/admin/config/ldap:使用 LdapConfigForm 更新 LDAP 启用状态。backend/open_webui/routers/auths.py:1130-1140
  • GET /api/v1/auths/admin/config/ldap/server:检索完整的 LdapServerConfig 对象。backend/open_webui/routers/auths.py:1074-1093
  • POST /api/v1/auths/admin/config/ldap/server:更新服务器连接详情。验证 host、app_dn 和 search_base 等必填字段是否已提供。backend/open_webui/routers/auths.py:1095-1122

来源:backend/open_webui/routers/auths.py:1074-1140

认证流程

LDAP 认证过程由 auths 路由器中的 ldap_auth 函数处理。

LDAP 认证序列

sequenceDiagram
    participant Client
    participant AuthRouter as [backend/open_webui/routers/auths.py]
    participant Config as AppConfig
    participant LDAP as LDAP 服务器 (ldap3)
    participant DB as 本地数据库 (SQLAlchemy)
    participant Groups as 组服务

    Client->>AuthRouter: POST /api/v1/auths/ldap {user, password}
    AuthRouter->>Config: 检查 ENABLE_LDAP

    alt LDAP 已禁用
        AuthRouter-->>Client: 400 LDAP 未启用
    end

    AuthRouter->>Config: 加载 LDAP 配置
    AuthRouter->>AuthRouter: 配置 TLS (Tls 对象)
    AuthRouter->>LDAP: 创建 Server + connection_app
    AuthRouter->>LDAP: 使用 LDAP_APP_DN 绑定

    alt 应用绑定失败
        AuthRouter-->>Client: 400 应用绑定失败
    end

    AuthRouter->>LDAP: search(username, attributes)

    alt 用户未找到
        AuthRouter-->>Client: 400 用户未找到
    end

    AuthRouter->>AuthRouter: 提取 email, cn, user_dn

    opt 启用 LDAP 组管理
        AuthRouter->>AuthRouter: 提取组 DN
        AuthRouter->>AuthRouter: 从组 DN 解析 CN
    end

    AuthRouter->>LDAP: 创建 connection_user
    AuthRouter->>LDAP: 使用 user_dn + password 绑定

    alt 用户认证失败
        AuthRouter-->>Client: 400 认证失败
    end

    AuthRouter->>DB: Users.get_user_by_email(email)

    alt 用户不存在
        AuthRouter->>DB: Auths.insert_new_auth()
        AuthRouter->>DB: apply_default_group_assignment()
    end

    AuthRouter->>DB: Auths.authenticate_user_by_email()
    AuthRouter->>AuthRouter: create_token(user.id)
    AuthRouter->>Client: 设置 cookie + 返回 SessionUserResponse

    opt 启用 LDAP 组管理
        AuthRouter->>Groups: create_groups_by_group_names()
        AuthRouter->>Groups: sync_groups_by_group_names()
    end

来源:backend/open_webui/routers/auths.py:231-500

实现细节
  1. TLS 初始化:系统使用 LDAP_VALIDATE_CERT、LDAP_CA_CERT_FILE 和 LDAP_CIPHERS 创建 ldap3.Tls 对象。backend/open_webui/routers/auths.py:252-257
  2. 应用绑定:使用 LDAP_APP_DN 建立初始连接,以搜索认证用户的完整专有名称(DN)。backend/open_webui/routers/auths.py:270-278
  3. 用户搜索:搜索过滤器对提供的用户名使用 escape_filter_chars 以防止 LDAP 注入。backend/open_webui/routers/auths.py:300-304
  4. 属性提取:从 LDAP_ATTRIBUTE_FOR_MAIL 属性中提取电子邮件地址。系统处理单个字符串、列表或属性对象。backend/open_webui/routers/auths.py:314-324
  5. 用户绑定:第二个连接尝试使用发现的 user_dn 和客户端提供的密码进行绑定。backend/open_webui/routers/auths.py:390-398
  6. 预置:如果用户不存在于本地 user 表中,则创建该用户。系统中的第一个用户自动分配 admin 角色;后续用户接收 DEFAULT_USER_ROLE。backend/open_webui/routers/auths.py:408-420

来源:backend/open_webui/routers/auths.py:231-500

组同步

Open WebUI 可以直接从 LDAP 属性(例如 memberOf)同步组成员身份。

组提取逻辑

系统解析专有名称(DN)以提取通用名称(CN)作为组标识符。

组同步数据流

graph TB
    subgraph "LDAP 条目 [ldap3.Entry]"
        GroupAttr["LDAP_ATTRIBUTE_FOR_GROUPS<br/>例如 'memberOf'"]
        GroupDNs["组 DN<br/>['CN=Admins,OU=Groups,...']"]
    end

    subgraph "DN 解析 [backend/open_webui/routers/auths.py]"
        ExtractValue["提取 .value 属性"]
        SplitDNs["按 ',' 分割每个 DN"]
        ExtractCN["查找以 'CN=' 开头的项"]
        ParseCN["提取 CN 值"]
    end

    subgraph "组名称"
        GroupList["user_groups = ['Admins', ...]"]
    end

    subgraph "数据库操作 [backend/open_webui/models/groups.py]"
        CreateCheck{ENABLE_LDAP_GROUP_CREATION?}
        CreateGroups["Groups.create_groups_by_group_names()"]
        SyncGroups["Groups.sync_groups_by_group_names()"]
    end

    GroupAttr --> GroupDNs
    GroupDNs --> ExtractValue
    ExtractValue --> SplitDNs
    SplitDNs --> ExtractCN
    ExtractCN --> ParseCN
    ParseCN --> GroupList

    GroupList --> CreateCheck
    CreateCheck -->|是| CreateGroups
    CreateCheck -->|否| SyncGroups
    CreateGroups --> SyncGroups

来源:backend/open_webui/routers/auths.py:326-387, backend/open_webui/routers/auths.py:472-480

组管理行为
  • 提取:代码遍历属性值。对于每个 DN,按逗号分割并搜索 CN= 前缀以识别组名称。backend/open_webui/routers/auths.py:354-377
  • 创建:如果 ENABLE_LDAP_GROUP_CREATION 为 true,则调用 Groups.create_groups_by_group_names 函数以确保所有 LDAP 组在本地存在。backend/open_webui/routers/auths.py:472-473
  • 同步:Groups.sync_groups_by_group_names 函数更新用户的本地成员身份以匹配 LDAP 状态。对于具有 admin 角色的用户跳过此操作,以防止意外从管理组中锁定。backend/open_webui/routers/auths.py:475-480

来源:backend/open_webui/routers/auths.py:326-387, backend/open_webui/routers/auths.py:472-480

安全考虑

密码处理

LDAP 密码永远不会存储在 Open WebUI 数据库中。在预置期间,生成随机 UUID 并使用 bcrypt 进行哈希处理,作为 auth 表中的占位符。backend/open_webui/routers/auths.py:411-413

连接安全
  • TLS:通过 ldap3.Tls 对象支持。backend/open_webui/routers/auths.py:252-257
  • 证书验证:由 LDAP_VALIDATE_CERT 控制。如果启用,服务器的证书必须根据 LDAP_CA_CERT_FILE 中提供的 CA 有效。backend/open_webui/routers/auths.py:241-244
  • 注入防护:在构建 LDAP 搜索过滤器之前,对所有用户提供的输入使用 ldap3.utils.conv 中的 escape_filter_chars 工具。backend/open_webui/routers/auths.py:301-304
会话管理

成功绑定后,使用 create_token 创建 JWT 令牌。backend/open_webui/routers/auths.py:442-445。然后,该令牌作为 httponly cookie 设置在响应中。backend/open_webui/routers/auths.py:448-461。

来源:backend/open_webui/routers/auths.py:241-461

错误处理

系统对常见的 LDAP 故障返回 400 Bad Request 或 401 Unauthorized:

场景状态码消息
LDAP 已禁用400"LDAP authentication is not enabled"
应用绑定失败400"Application account bind failed"
用户未找到400"User not found in the LDAP server"
密码无效400"Authentication failed."
缺少电子邮件400"User does not have a valid email address."

来源:backend/open_webui/routers/auths.py:221-222, backend/open_webui/routers/auths.py:277-278, backend/open_webui/routers/auths.py:306-307, backend/open_webui/routers/auths.py:314-315, backend/open_webui/routers/auths.py:397-398