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

概览

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

令牌声明

必需声明

提交给 ClickHouse 的每个 JWT 都必须包含以下声明:
声明说明
alg签名算法 (请求头声明) 。支持的值:HS256RS256ES256
exp过期时间。用于设置临时用户的 valid_until
iat签发时间。用于防止同一身份的旧令牌被重放。
iss签发方。会与提供商预期的签发方进行匹配。
sub主体。会成为生成用户名的一部分。
aud受众。会与提供商预期的受众进行匹配。
使用基于 JWKS 的密钥解析时,还必须提供 kid (密钥 ID) 请求头声明。
JWKS 模式仅支持 RSA 密钥静态密钥提供商可以接受 HS256RS256ES256 中的任意一种,而基于 JWKS 的提供商只接受 ktyRSA 的 JWK (即使用 RS256 签名的令牌) 。使用 HMAC (HS256) 或 EC (ES256) 密钥签名的令牌无法通过 JWKS 端点验证,因此会被拒绝。

其他已识别的声明

声明描述
nbf生效时间。在此声明不是必需的;但如果提供了该声明,则在该时间之前,令牌会被拒绝。
jti保留字段。令牌中可以包含该声明,但当前不会对其进行验证或使用。

可选 claims

Claim默认名称描述
授权clickhouse:grants由 SQL GRANT 片段组成的 JSON 数组,例如 ["SELECT ON db.*", "INSERT ON db.table1"]。每个元素都会被解析为 GRANT 语句的主体。
角色clickhouse:roles要分配的角色名称 JSON 数组,例如 ["analyst", "reader"]
如果身份提供商使用不同的命名约定,可以将默认的 claim 名称重映射为自定义 claim 名称。

令牌标头和载荷示例

{
  "alg": "RS256",
  "kid": "my-key-id"
}
{
  "iss": "https://idp.example.com",
  "sub": "jane.doe",
  "aud": "my-clickhouse-cluster",
  "exp": 1719504000,
  "iat": 1719500400,
  "clickhouse:grants": ["SELECT ON analytics.*", "INSERT ON analytics.events"],
  "clickhouse:roles": ["analyst"]
}

临时用户的行为

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

身份与命名

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

访问权限

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

令牌新鲜度

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

生命周期与垃圾回收

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

持久化访问分配

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

与普通用户的区别

FeatureJWT 用户普通用户
创建根据标记声明自动创建CREATE USER 语句
存储仅驻留于内存中 (临时)磁盘、ZooKeeper 或配置文件
CREATE USER ... IDENTIFIED WITH jwt不支持 (会抛出异常)支持所有其他认证类型
ALTER USER / DROP USER不支持支持
备份和恢复不包含包含
用户名自动生成、可变由管理员指定、固定
UUID根据 iss+sub+aud 确定性生成创建时随机生成
生命周期受标记 exp 限定直到被显式删除
访问权限从标记声明派生,并受权限上限约束通过 GRANT 显式授予
主机限制按提供商网络配置按用户 HOST 子句设置
设置 profile可按 UUID 分配 (持久)可直接配置
配额和行策略可按 UUID 分配 (持久)可直接配置
默认角色不可配置可配置

SQL SECURITY DEFINER 视图

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

客户端使用

直接传入令牌

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

HTTP 接口

Authorization 请求头中以 Bearer 令牌的形式发送该令牌:
curl -H 'Authorization: Bearer <your_jwt_token>' \
    'https://your-instance.clickhouse.cloud:8443/?query=SELECT+currentUser()'
始终通过 HTTPS 发送 JWT。通过明文 HTTP 发送的 Bearer 令牌会暴露给网络路径上的任何人,这等同于泄露凭证。

OAuth2 设备代码登录

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

ClickHouse Cloud 内置 JWT 身份验证器

每个 ClickHouse Cloud 服务都带有一个预定义的 JWT 身份验证器,供 SQL 控制台和 clickhouse-client--login 流程使用。该身份验证器配置如下:
参数
iss (签发方)ClickHouse
aud (受众)服务 UUID (可在 Cloud 控制台 URL 中看到)
sub (主体)你的 ClickHouse Cloud 账户邮箱地址
此内置身份验证器的权限上限设置为 default_role 角色和 default 用户。这意味着,任何 JWT 用户的实际权限都会与这两个实体所拥有的授权取交集,因此令牌的权限绝不会提升到超出 default_roledefault 允许范围的级别。 使用此身份验证器无需进行任何配置。服务创建时会自动为其预配。

服务器间通信

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

故障排除

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