认证方式(中文译文)
原始 DeepWiki 页面:https://deepwiki.com/open-webui/open-webui/11.1-authentication-methods
翻译时间:2026-06-09T16:10:28.577Z
翻译模型:deepseek-chat
原文字符数:12784
项目:Open WebUI (open-webui)
---
认证方法
相关源文件
以下文件为本 wiki 页面的生成提供了上下文:
backend/open_webui/config.pybackend/open_webui/env.pybackend/open_webui/main.pybackend/open_webui/routers/auths.pybackend/open_webui/utils/auth.pybackend/open_webui/utils/oauth.pysrc/lib/apis/auths/index.tssrc/lib/components/chat/Settings/Account.sveltesrc/lib/components/chat/Settings/Audio.sveltesrc/routes/auth/+page.svelte
目的与范围
本文档介绍 Open WebUI 中用于验证用户身份和管理访问凭证的认证机制。涵盖的主要认证方法包括:JWT 令牌、API 密钥、OAuth 2.1、LDAP 以及受信任头部认证。关于授权和访问控制的信息,请参阅访问控制与 RBAC。关于 OAuth 特定配置和提供程序设置,请参阅OAuth 集成。关于 LDAP 特定配置,请参阅LDAP 集成。
---
认证架构概述
Open WebUI 实现了灵活的多方法认证系统,同时支持交互式用户会话和程序化 API 访问。认证层设计用于处理从单用户安装到具有集中身份管理的企业环境等多种部署场景。
认证方法流程图
graph TB
Request["传入 HTTP 请求"]
Request --> CheckAuth["检查认证"]
CheckAuth -->|"Authorization: Bearer sk-..."| APIKey["API 密钥认证"]
CheckAuth -->|"Authorization: Bearer jwt..."| JWT["JWT 令牌认证"]
CheckAuth -->|"Cookie: token=jwt..."| JWT
CheckAuth -->|"存在 Trusted-Header"| TrustedHeader["受信任头部认证"]
APIKey --> ValidateAPIKey["get_current_user_by_api_key()"]
ValidateAPIKey --> APIKeyDB[("Users.get_user_by_api_key()")]
APIKeyDB -->|有效| Authenticated["已认证用户"]
APIKeyDB -->|无效| Reject["401 未授权"]
JWT --> DecodeJWT["decode_token()"]
DecodeJWT --> CheckRevoked{"检查是否已撤销"}
CheckRevoked -->|"Redis 查找"| RedisCheck[("Redis token:jti:revoked")]
RedisCheck -->|未撤销| GetUser["Users.get_user_by_id()"]
RedisCheck -->|已撤销| Reject
CheckRevoked -->|"无 Redis"| GetUser
GetUser -->|有效| Authenticated
GetUser -->|无效| Reject
TrustedHeader --> ExtractEmail["从头部提取 email"]
ExtractEmail --> AutoProvision{"用户是否存在?"}
AutoProvision -->|否| CreateUser["signup_handler()"]
AutoProvision -->|是| LoadUser["Auths.authenticate_user_by_email()"]
CreateUser --> Authenticated
LoadUser --> Authenticated
Reject --> DeleteCookies["删除认证 cookies"]
来源: backend/open_webui/utils/auth.py:275-374,backend/open_webui/routers/auths.py:97-150
---
JWT 令牌认证
JWT(JSON Web Token)认证是 Open WebUI 中用户会话的主要方法。令牌使用 WEBUI_SECRET_KEY 签名,并包含最少的声明以保持载荷体积小巧。
令牌结构与生命周期
| 组件 | 描述 | 配置 |
|---|---|---|
| 签名算法 | HS256 (HMAC-SHA256) | ALGORITHM = 'HS256' backend/open_webui/utils/auth.py:51 |
| 签名密钥 | 对称密钥 | SESSION_SECRET = WEBUI_SECRET_KEY backend/open_webui/utils/auth.py:50 |
| 标准声明 | id(用户 ID)、exp(过期时间)、jti(令牌 ID)、iat(签发时间) | 由 create_token() 设置 backend/open_webui/utils/auth.py:200-211 |
| 默认过期时间 | 可通过 JWT_EXPIRES_IN 配置 | 由 parse_duration() 解析 backend/open_webui/routers/auths.py:114 |
| 存储方式 | 名为 token 的 HttpOnly cookie | 通过 response.set_cookie() 设置 backend/open_webui/routers/auths.py:127-135 |
| Cookie 属性 | httponly=True,samesite 和 secure 可配置 | WEBUI_AUTH_COOKIE_SAME_SITE、WEBUI_AUTH_COOKIE_SECURE backend/open_webui/routers/auths.py:132-133 |
来源: backend/open_webui/utils/auth.py:50-52,backend/open_webui/utils/auth.py:200-211
令牌创建与验证流程
sequenceDiagram
participant Client as "前端客户端"
participant AuthRouter as "backend/open_webui/routers/auths.py"
participant CreateToken as "create_token()"
participant JWT as "PyJWT 库"
participant Response as "HTTP 响应"
participant GetUser as "get_current_user()"
participant Decode as "decode_token()"
participant Redis as "Redis 缓存"
participant UsersDB as "open_webui.models.users.Users"
Client->>AuthRouter: POST /signin 或 /ldap
AuthRouter->>AuthRouter: 验证凭据
AuthRouter->>CreateToken: create_token(data={"id": user.id})
CreateToken->>CreateToken: 生成 jti (uuid4)
CreateToken->>CreateToken: 计算 exp (datetime + delta)
CreateToken->>JWT: jwt.encode(payload, SESSION_SECRET, ALGORITHM)
JWT-->>CreateToken: encoded_jwt
CreateToken-->>AuthRouter: 令牌字符串
AuthRouter->>Response: Set-Cookie: token=...; HttpOnly; Secure
Response-->>Client: 200 OK + cookie 中的令牌
Note over Client,UsersDB: 后续请求
Client->>GetUser: 携带 Authorization 或 Cookie 的请求
GetUser->>GetUser: 从头部/cookie 提取令牌
GetUser->>Decode: decode_token(token)
Decode->>Decode: jwt.decode(token, SESSION_SECRET, [ALGORITHM])
Decode-->>GetUser: {"id": "...", "jti": "...", "exp": ...}
GetUser->>GetUser: 检查 exp 时间戳
alt Redis 可用
GetUser->>Redis: GET token:{jti}:revoked
Redis-->>GetUser: null(未撤销)
end
GetUser->>UsersDB: get_user_by_id(data["id"])
UsersDB-->>GetUser: UserModel
GetUser-->>Client: 认证请求继续执行
来源: backend/open_webui/utils/auth.py:200-228,backend/open_webui/utils/auth.py:275-374,backend/open_webui/routers/auths.py:97-150
会话创建辅助函数
create_session_response() 函数集中了多个认证端点(包括 /signin、/signup、/ldap 和 token_exchange)的会话创建逻辑 backend/open_webui/routers/auths.py:100-102。
该辅助函数:
- 解析
JWT_EXPIRES_IN配置以确定令牌生命周期backend/open_webui/routers/auths.py:114。 - 调用
create_token()生成 JWTbackend/open_webui/routers/auths.py:119-122。 - 可选地在响应上设置
tokencookie,属性为httponly=Truebackend/open_webui/routers/auths.py:127-135。 - 通过
get_permissions()获取用户权限backend/open_webui/routers/auths.py:137。 - 返回包含
token、token_type、expires_at和用户个人资料数据的标准化响应字典backend/open_webui/routers/auths.py:139-149。
来源: backend/open_webui/routers/auths.py:100-149
令牌撤销
令牌撤销通过 invalidate_token() 函数使用 Redis 作为分布式黑名单实现 backend/open_webui/utils/auth.py:230-253。
invalidate_token() 函数:
- 解码令牌以提取
jti(JWT ID)和exp(过期时间戳)backend/open_webui/utils/auth.py:231-240。 - 计算 TTL 为
exp - current_time,使撤销条目自动过期backend/open_webui/utils/auth.py:243-245。 - 在 Redis 中存储
{REDIS_KEY_PREFIX}:auth:token:{jti}:revoked,值为"1"backend/open_webui/utils/auth.py:249-251。
在认证过程中,is_valid_token() 在接受令牌前检查撤销标志 backend/open_webui/utils/auth.py:222-236。
来源: backend/open_webui/utils/auth.py:222-253,backend/open_webui/env.py:37
---
API 密钥认证
API 密钥为程序化访问提供无状态认证。密钥遵循 sk-{32_hex_chars} 格式。
API 密钥结构
| 方面 | 实现 |
|---|---|
| 格式 | sk-{uuid.uuid4().hex}(前缀 + 32 个十六进制字符)backend/open_webui/utils/auth.py:260-262 |
| 生成 | create_api_key() 位于 backend/open_webui/utils/auth.py:260-262 |
| 存储 | users.api_key 列,使用 bcrypt 哈希 |
| 验证 | Users.get_user_by_api_key() 查询数据库 backend/open_webui/utils/auth.py:381 |
| 权限检查 | 非管理员用户需要 features.api_keys 权限 backend/open_webui/utils/auth.py:392-397 |
来源: backend/open_webui/utils/auth.py:260-408
---
OAuth 2.1 集成
OAuth 2.1 支持联合认证。Open WebUI 支持静态提供程序配置和 MCP 服务器的动态客户端注册。
OAuth 令牌管理
OAuth 会话和令牌通过 open_webui.utils.oauth 管理。令牌可以被规范化以确保其具有过期时间戳 backend/open_webui/utils/oauth.py:148-175。
graph TD
subgraph "open_webui.utils.oauth"
OAuth["Authlib OAuth 集成"]
Normalize["_normalize_token_expiry()"]
Encrypt["encrypt_data()"]
Decrypt["decrypt_data()"]
end
subgraph "存储与安全"
OAuthSessionsDB[("OAuthSessions 模型")]
Fernet["Fernet 加密 (AES)"]
Config["OAUTH_CLIENT_INFO_ENCRYPTION_KEY"]
end
OAuth --> Normalize
Normalize --> Encrypt
Encrypt --> Fernet
Fernet --> Config
Decrypt --> Fernet
OAuthSessionsDB --> Decrypt
来源: backend/open_webui/utils/oauth.py:148-206,backend/open_webui/models/oauth_sessions.py:1-30
动态客户端注册
Open WebUI 可以动态注册为 MCP 工具服务器的 OAuth 客户端 backend/open_webui/utils/oauth.py:95-108。它使用 OAuthClientMetadata 管理注册详情,并使用 Fernet 对敏感客户端信息进行加密 backend/open_webui/utils/oauth.py:178-201。
来源: backend/open_webui/utils/oauth.py:95-201
---
LDAP 认证
LDAP 认证允许与目录服务集成。
LDAP 认证流程
auths.py 中的 /ldap 端点处理认证过程 backend/open_webui/routers/auths.py:113-143:
- 前端请求:Svelte 客户端调用
ldapUserSignInsrc/lib/apis/auths/index.ts:113-143。 - 后端绑定:服务器建立与 LDAP 服务器的连接
backend/open_webui/routers/auths.py:88。 - 用户预置:绑定成功后,系统确保存在本地用户记录,并返回 JWT 会话
backend/open_webui/routers/auths.py:100-150。
来源: backend/open_webui/routers/auths.py:113-143,src/lib/apis/auths/index.ts:113-143
---
受信任头部认证
受信任头部认证允许通过注入身份头部的反向代理实现 SSO。
配置与验证
Open WebUI 查找 WEBUI_AUTH_TRUSTED_EMAIL_HEADER 中定义的头部 backend/open_webui/env.py:42。如果启用,系统信任上游代理在头部中提供的身份。
在 get_current_user() 的会话验证过程中,系统执行安全检查以确保身份保持一致 backend/open_webui/utils/auth.py:334-342。
来源: backend/open_webui/env.py:42,backend/open_webui/utils/auth.py:334-342
---
安全与令牌管理
密码哈希
密码使用带盐值的 bcrypt 进行哈希 backend/open_webui/utils/auth.py:166-168。验证通过将明文密码与存储的哈希值进行比较来完成 backend/open_webui/utils/auth.py:185-194。
Fernet 加密
敏感数据(如 OAuth 令牌)使用 Fernet 加密 backend/open_webui/utils/oauth.py:178-191。加密密钥源自 OAUTH_CLIENT_INFO_ENCRYPTION_KEY backend/open_webui/utils/oauth.py:180-184。
速率限制
登录端点上的暴力破解防护由 signin_rate_limiter 提供,该限流器使用 Redis 跟踪尝试次数 backend/open_webui/routers/auths.py:97-98。
来源: backend/open_webui/utils/auth.py:166-194,backend/open_webui/utils/oauth.py:178-191,backend/open_webui/routers/auths.py:97-98