Skip to main content
ClickHouse 可以使用 JSON Web Token (JWT) 对用户进行身份验证。与其他外部身份验证器 (如 LDAP 或 Kerberos) 不同,JWT 身份验证不会验证预先存在用户的身份。相反,它会根据嵌入在每个令牌中的声明动态创建临时用户。这些用户仅存在于内存中,其访问权限由令牌声明派生,并会在令牌过期后自动移除。 这使得 JWT 身份验证与基于密码或证书的方法有本质区别:不存在 CREATE USER ... IDENTIFIED WITH jwt 语句,尝试这样做会引发异常。JWT 用户完全由令牌的生命周期管理。

概览

身份验证流程如下:
  1. 客户端通过支持的传输机制之一提交已签名的 JWT (HTTP Authorization: Bearer 请求头、TCP 原生协议,或 gRPC jwt 字段) 。
  2. ClickHouse 验证令牌签名。
  3. 验证必需的声明 (exp、iat、iss、sub、aud) 。
  4. 在内存中创建一个临时用户,其访问权限由令牌声明 clickhouse:grants 和 clickhouse:roles 推导得出,并与权限上限取交集。
  5. 当令牌过期时,后台垃圾回收任务会移除该用户。

令牌声明

必需声明

提交给 ClickHouse 的每个 JWT 都必须包含以下声明: 使用基于 JWKS 的密钥解析时,还必须提供 kid (密钥 ID) 请求头声明。
JWKS 模式仅支持 RSA 密钥静态密钥提供商可以接受 HS256、RS256 或 ES256 中的任意一种,而基于 JWKS 的提供商只接受 kty 为 RSA 的 JWK (即使用 RS256 签名的令牌) 。使用 HMAC (HS256) 或 EC (ES256) 密钥签名的令牌无法通过 JWKS 端点验证,因此会被拒绝。

其他已识别的声明

可选 claims

令牌标头和载荷示例

临时用户的行为

JWT 用户与常规 ClickHouse 用户在几个重要方面有所不同。

身份与命名

每个 JWT 用户都会获得一个根据 iss、sub 和 aud claims 计算出的确定性 UUID。该 UUID 在不同登录之间是稳定的。同一用户即使用不同的令牌多次登录 (只要签发方、主体和受众相同) ,获得的 UUID 也始终相同。 不过,用户名是易变的。其构造方式如下:
<claims_hash> 部分会在 clickhouse:roles 或 clickhouse:grants 声明发生变化时相应变化。这意味着,即使是同一身份,具有不同角色或授权集合的令牌也会生成不同的用户名。

访问权限

有效访问权限按如下方式计算:
其中,permission_limit 是作为上限参考而配置的角色或用户所拥有的访问权限集合。令牌请求的任何超出该上限的权限都会被静默丢弃。

令牌新鲜度

ClickHouse 会跟踪每个稳定身份最近一次通过身份验证的令牌的 iat (签发时间) 声明。如果提供的令牌其 iat 等于或早于已存储的值,服务器会复用现有的临时用户,而不会重新评估声明。这样可以防止旧令牌降低用户权限。

生命周期与垃圾回收

临时用户会在令牌首次通过身份验证时创建,并在 valid_until (由 exp 推导得出) 到期后,由后台垃圾回收任务删除。GC 间隔由 gc_interval 参数控制 (默认值:5 分钟) 。 在两次 GC 运行之间,已过期的用户可能仍会显示在 system.users 中,但已无法再进行身份验证。

持久化访问分配

由于 UUID 是固定的,你可以使用 SQL 语句将 profile、配额、行策略和列脱敏策略分配给 JWT 用户。这些分配会持久保存在 access control 存储中 (磁盘上或 ZooKeeper 中) ,并且在令牌过期和重新身份验证后依然有效。 通过用户当前的用户名引用该用户:
对于给定的 identity,在用户处于活跃状态时,可在 system.users 的 name 和 id 列中找到其用户名和 UUID。
请注意,ALTER USER 不能直接用于 JWT 用户,因为它们是只读的。要分配 settings profile、配额或策略,请使用上文所示的 ALTER SETTINGS PROFILE、ALTER QUOTA 或 ALTER ROW POLICY 语句。

与普通用户的区别

SQL SECURITY DEFINER 视图

当临时 JWT 用户使用 SQL SECURITY DEFINER 创建视图时,服务器会自动为该用户创建一个持久的影子副本,作为该视图的定义者。该影子用户:
  • 名称为 <original_jwt_username>:definer
  • 具有 NO_AUTHENTICATION (不能用于登录)
  • 保留创建视图时原始 JWT 用户拥有的相同访问权限
这样可以确保在临时用户的令牌过期、原始用户被垃圾回收机制清理后,视图仍能继续正常工作。

客户端使用

直接传入令牌

使用 clickhouse-client 的 --jwt 选项,通过预先获取的令牌进行身份验证:
--jwt 标志与 --user 互斥。指定 --jwt 时,用户名将从令牌中获取。

HTTP 接口

在 Authorization 请求头中以 Bearer 令牌的形式发送该令牌:
始终通过 HTTPS 发送 JWT。通过明文 HTTP 发送的 Bearer 令牌会暴露给网络路径上的任何人,这等同于泄露凭证。

OAuth2 设备代码登录

clickhouse-client 支持通过 --login 标志使用交互式 OAuth2 设备代码流程。对于 ClickHouse Cloud 端点,客户端会自动执行令牌交换,以获取 ClickHouse 专用 JWT。令牌会在会话期间自动刷新,整个过程对用户透明。获取到新令牌后,客户端会自动重新连接。

ClickHouse Cloud 内置 JWT 身份验证器

每个 ClickHouse Cloud 服务都带有一个预定义的 JWT 身份验证器,供 SQL 控制台和 clickhouse-client 的 --login 流程使用。该身份验证器配置如下: 此内置身份验证器的权限上限设置为 default_role 角色和 default 用户。这意味着,任何 JWT 用户的实际权限都会与这两个实体所拥有的授权取交集,因此令牌的权限绝不会提升到超出 default_role 和 default 允许范围的级别。 使用此身份验证器无需进行任何配置。服务创建时会自动为其预配。

服务器间通信

当查询被转发到另一分片或副本时,JWT 令牌会包含在服务器间协议中。远程节点会独立重新验证该令牌,并创建自己的临时用户。

故障排除

  • 未授予访问权限: 引用的角色或用户可能缺少所需的授权。请确保 clickhouse:roles 中引用的角色存在,并且已授予相应权限。
  • 令牌被拒绝: 请验证令牌中的 iss、aud 以及签名算法是否与 JWT 提供商的要求一致。如果使用 JWKS,请确保令牌的 kid 与提供商密钥集中的某个密钥匹配。
  • 用户在两次查询之间消失: 临时用户会在令牌过期后被移除。对于长时间运行的会话,请使用支持令牌刷新的客户端 (例如 --login 模式) 。
  • CREATE USER ... IDENTIFIED WITH jwt 失败: 这是预期行为。JWT 用户无法通过 DDL 创建。它们完全由令牌生命周期管理。
最后修改于 2026年6月10日