> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-vortex-format.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> USER 参考文档

# CREATE USER

创建[用户账户](/zh/concepts/features/security/access-rights#user-account-management)。

语法：

```sql theme={null}
CREATE USER [IF NOT EXISTS | OR REPLACE] name1 [, name2 [,...]] [ON CLUSTER cluster_name]
    [{VALID UNTIL datetime | VALID FOR interval}]
    [NOT IDENTIFIED | IDENTIFIED {[WITH {plaintext_password | sha256_password | sha256_hash | double_sha1_password | double_sha1_hash}] BY {'password' | 'hash'}} | WITH NO_PASSWORD | {WITH ldap SERVER 'server_name'} | {WITH kerberos [REALM 'realm']} | {WITH ssl_certificate CN 'common_name' | SAN 'TYPE:subject_alt_name'} | {WITH ssh_key BY KEY 'public_key' TYPE 'ssh-rsa|...'} | {WITH http SERVER 'server_name' [SCHEME 'Basic']} [{VALID UNTIL datetime | VALID FOR interval}] [GRANTS (privilege ON object [,...])]
    [, {[{plaintext_password | sha256_password | sha256_hash | ...}] BY {'password' | 'hash'}} | {ldap SERVER 'server_name'} | {...} | ... [,...]]]
    [HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]
    [IN access_storage_type]
    [ROLE role [,...]]
    [DEFAULT ROLE role [,...]]
    [DEFAULT DATABASE database | NONE]
    [GRANTEES {user | role | ANY | NONE} [,...] [EXCEPT {user | role} [,...]]]
    [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY | WRITABLE] | PROFILE 'profile_name'] [,...]
```

`ON CLUSTER` 子句支持在集群中创建用户，参见 [分布式 DDL](/zh/reference/statements/distributed-ddl)。

<div id="identification">
  ## 身份标识
</div>

用户身份标识有多种方式：

* `IDENTIFIED WITH no_password`
* `IDENTIFIED WITH plaintext_password BY 'qwerty'`
* `IDENTIFIED WITH sha256_password BY 'qwerty'` or `IDENTIFIED BY 'password'`
* `IDENTIFIED WITH sha256_hash BY 'hash'` or `IDENTIFIED WITH sha256_hash BY 'hash' SALT 'salt'`
* `IDENTIFIED WITH double_sha1_password BY 'qwerty'`
* `IDENTIFIED WITH double_sha1_hash BY 'hash'`
* `IDENTIFIED WITH bcrypt_password BY 'qwerty'`
* `IDENTIFIED WITH bcrypt_hash BY 'hash'`
* `IDENTIFIED WITH ldap SERVER 'server_name'`
* `IDENTIFIED WITH kerberos` or `IDENTIFIED WITH kerberos REALM 'realm'`
* `IDENTIFIED WITH ssl_certificate CN 'mysite.com:user'`
* `IDENTIFIED WITH ssh_key BY KEY 'public_key' TYPE 'ssh-rsa', KEY 'another_public_key' TYPE 'ssh-ed25519'`
* `IDENTIFIED WITH http SERVER 'http_server'` or `IDENTIFIED WITH http SERVER 'http_server' SCHEME 'basic'`
* `IDENTIFIED BY 'qwerty'`

密码复杂度要求可在 [config.xml](/zh/concepts/features/configuration/server-config/configuration-files) 中修改。下面是一个配置示例，要求密码长度至少为 12 个字符，且包含 1 个数字。每条密码复杂度规则都需要一个用于匹配密码的正则表达式，以及对该规则的说明。

```xml theme={null}
<clickhouse>
    <password_complexity>
        <rule>
            <pattern>.{12}</pattern>
            <message>be at least 12 characters long</message>
        </rule>
        <rule>
            <pattern>\p{N}</pattern>
            <message>contain at least 1 numeric character</message>
        </rule>
    </password_complexity>
</clickhouse>
```

<Note>
  在 ClickHouse Cloud 中，默认情况下，密码必须满足以下复杂度要求：

  * 长度至少为 12 个字符
  * 至少包含 1 个数字
  * 至少包含 1 个大写字母
  * 至少包含 1 个小写字母
  * 至少包含 1 个特殊字符
</Note>

<div id="examples">
  ## 示例
</div>

1. 以下用户名为 `name1`，且无需密码——显然，这样几乎没有什么安全性可言：

   ```sql theme={null}
   CREATE USER name1 NOT IDENTIFIED
   ```

2. 要指定明文密码：

   ```sql theme={null}
   CREATE USER name2 IDENTIFIED WITH plaintext_password BY 'my_password'
   ```

<Tip>
  密码会以 SQL 文本文件的形式存储在 `/var/lib/clickhouse/access` 中，因此不建议使用 `plaintext_password`。请改用 `sha256_password`，如下一个示例所示...
</Tip>

3. 最常见的做法是使用经过 SHA-256 哈希处理的密码。当你指定 `IDENTIFIED WITH sha256_password` 时，ClickHouse 会自动为你计算密码哈希。例如：

   ```sql theme={null}
   CREATE USER name3 IDENTIFIED WITH sha256_password BY 'my_password'
   ```

   现在，`name3` 用户可以使用 `my_password` 登录，但密码实际以上面的哈希值形式存储。系统会在 `/var/lib/clickhouse/access` 中创建以下 SQL 文件，并在服务器启动时执行：

   ```bash theme={null}
   /var/lib/clickhouse/access $ cat 3843f510-6ebd-a52d-72ac-e021686d8a93.sql
   ATTACH USER name3 IDENTIFIED WITH sha256_hash BY '0C268556C1680BEF0640AAC1E7187566704208398DA31F03D18C74F5C5BE5053' SALT '4FB16307F5E10048196966DD7E6876AE53DE6A1D1F625488482C75F14A5097C7';
   ```

<Tip>
  如果你已经为某个用户名生成了哈希值及其对应的 salt 值，则可以使用 `IDENTIFIED WITH sha256_hash BY 'hash'` 或 `IDENTIFIED WITH sha256_hash BY 'hash' SALT 'salt'`。对于使用 `SALT` 的 `sha256_hash` 身份验证，哈希必须基于 'password' 和 'salt' 拼接后的结果计算得出。
</Tip>

4. `double_sha1_password` 通常并不常用，但在配合需要它的客户端时会很有帮助 (例如 MySQL 接口) ：

   ```sql theme={null}
   CREATE USER name4 IDENTIFIED WITH double_sha1_password BY 'my_password'
   ```

   ClickHouse 会生成并执行以下查询：

   ```response theme={null}
   CREATE USER name4 IDENTIFIED WITH double_sha1_hash BY 'CCD3A959D6A004B9C3807B728BC2E55B67E10518'
   ```

5. `bcrypt_password` 是存储密码时最安全的选项。它使用 [bcrypt](https://en.wikipedia.org/wiki/Bcrypt) 算法，即使密码哈希泄露，也能有效抵御暴力破解攻击。

   ```sql theme={null}
   CREATE USER name5 IDENTIFIED WITH bcrypt_password BY 'my_password'
   ```

   使用此方法时，密码长度限制为 72 个字符。
   bcrypt work factor 参数用于定义计算哈希和验证密码所需的计算量与时间，可在服务器配置中修改：

   ```xml theme={null}
   <bcrypt_workfactor>12</bcrypt_workfactor>
   ```

   work factor 必须介于 4 到 31 之间，默认值为 12。

<Warning>
  对于需要高频身份验证的应用，
  请考虑使用其他身份验证方法，
  因为在较高 work factor 下 bcrypt 的计算开销较大。
</Warning>

6. 也可以省略密码类型：

   ```sql theme={null}
   CREATE USER name6 IDENTIFIED BY 'my_password'
   ```

   在这种情况下，ClickHouse 将使用服务器配置中指定的默认密码类型：

   ```xml theme={null}
   <default_password_type>sha256_password</default_password_type>
   ```

   可用的密码类型有：`plaintext_password`、`sha256_password`、`double_sha1_password`。

7. 可以指定多种身份验证方法：

   ```sql theme={null}
   CREATE USER user1 IDENTIFIED WITH plaintext_password by '1', bcrypt_password by '2', plaintext_password by '3''
   ```

注：

1. 较旧版本的 ClickHouse 可能不支持多种身份验证方法的语法。因此，如果 ClickHouse 服务器 中存在此类用户，而又被降级到不支持该语法的版本，这些用户将无法使用，并且部分与用户相关的操作也会失效。为了平稳降级，必须在降级前将所有用户都设置为仅包含一种身份验证方法。或者，如果 server 未按正确流程就已降级，则应删除这些有问题的用户。
2. 出于安全原因，`no_password` 不能与其他身份验证方法同时存在。因此，只有当它是查询中唯一的身份验证方法时，您才可以指定
   `no_password`。

<div id="user-host">
  ## 用户主机
</div>

用户主机是指可用于建立与 ClickHouse 服务器 连接的主机。可以在查询的 `HOST` 部分中按以下方式指定主机：

* `HOST IP 'ip_address_or_subnetwork'` — 用户只能从指定的 IP 地址或某个[子网](https://en.wikipedia.org/wiki/Subnetwork)连接到 ClickHouse 服务器。示例：`HOST IP '192.168.0.0/16'`、`HOST IP '2001:DB8::/32'`。在生产环境中，建议仅指定 `HOST IP` 元素 (IP 地址及其掩码) ，因为使用 `host` 和 `host_regexp` 可能会带来额外延迟。
* `HOST ANY` — 用户可以从任何位置连接。这是默认选项。
* `HOST LOCAL` — 用户只能在本地连接。
* `HOST NAME 'fqdn'` — 用户主机可以指定为 FQDN。例如：`HOST NAME 'mysite.com'`。
* `HOST REGEXP 'regexp'` — 指定用户主机时，可以使用 [pcre](http://www.pcre.org/) 正则表达式。例如：`HOST REGEXP '.*\.mysite\.com'`。
* `HOST LIKE 'template'` — 允许使用 [LIKE](/zh/reference/functions/regular-functions/string-search-functions#like) 运算符来过滤用户主机。例如，`HOST LIKE '%'` 等同于 `HOST ANY`，`HOST LIKE '%.mysite.com'` 会过滤 `mysite.com` 域下的所有主机。

指定主机的另一种方式是在用户名后使用 `@` 语法。示例：

* `CREATE USER mira@'127.0.0.1'` — 等同于 `HOST IP` 语法。
* `CREATE USER mira@'localhost'` — 等同于 `HOST LOCAL` 语法。
* `CREATE USER mira@'192.168.%.%'` — 等同于 `HOST LIKE` 语法。

<Tip>
  ClickHouse 将 `user_name@'address'` 视为一个完整的用户名。因此，严格来说，你可以创建多个 `user_name` 相同、但 `@` 后部分不同的用户。不过，我们不建议这样做。
</Tip>

<div id="valid-until-clause">
  ## VALID UNTIL 子句
</div>

用于指定身份验证方法的到期日期，以及可选的到期时间。它接受字符串参数。建议日期时间采用 `YYYY-MM-DD [hh:mm:ss] [timezone]` 格式，其中 `[timezone]` 必须是数值偏移量 (如 `+09:00`) ，或 `UTC`、`GMT`、`Z`、`MSK`、`MSD` 之一；不支持 `Asia/Tokyo` 这类命名 IANA 时区 (请参阅下方说明) 。默认情况下，此参数为 `'infinity'`。可接受的截止时间范围为 `1900-01-01 00:00:00 UTC` 至 `9999-12-31 09:59:59 UTC`——后者是在所有时区中均仍处于 9999 年内的最晚时刻，因此存储的时刻在显示时绝不会被截断。过去的截止时间表示凭据已过期。早于 `1970-01-01 00:00:01 UTC` 的截止时间仅会作为“已过期”标记被接受：它们会被规范化为最早的过期时刻，即 Unix 纪元后一秒 (`1970-01-01 00:00:01 UTC`) ，因此 `SHOW CREATE USER` 显示的是该时刻，而非您指定的截止时间。自该时刻起的截止时间将按原样存储。

截止时间以绝对时刻存储，但 `SHOW CREATE USER` 和 [`system.users`](/zh/reference/system-tables/users) 会按服务器或会话时区显示它，因此同一存储时刻在配置不同的服务器上会显示为不同的本地时间文本：例如，上述规范化后的过期时刻在 `UTC` 服务器上显示为 `1970-01-01 00:00:01`，在 `Pacific/Kiritimati` 服务器上则显示为 `1970-01-01 14:00:01`。实际执行时始终使用存储的时刻，而非其显示结果。

子句的位置决定其适用的身份验证方法：

* 位于 `IDENTIFIED` 子句之前 (或查询完全未指定身份验证方法时) ：截止时间为用户级截止时间，适用于该用户的所有身份验证方法。
* 位于某个身份验证方法之后：截止时间仅适用于该方法。因此，写在整个 `IDENTIFIED` 列表之后的子句只会绑定到最后一个方法，之前的方法不会过期。

示例：

* `CREATE USER name1 VALID UNTIL '2025-01-01'`
* `CREATE USER name1 VALID UNTIL '2025-01-01 12:00:00 UTC'`
* `CREATE USER name1 VALID UNTIL '2025-01-01 12:00:00 +09:00'`
* `CREATE USER name1 VALID UNTIL 'infinity'`
* `CREATE USER name1 VALID UNTIL '2025-01-01' IDENTIFIED WITH plaintext_password BY 'password_1', bcrypt_password BY 'password_2'` — 用户级截止时间适用于两种方法。
* `CREATE USER name1 IDENTIFIED WITH plaintext_password BY 'no_expiration', bcrypt_password BY 'expiration_set' VALID UNTIL '2025-01-01'` — 截止时间仅适用于 `bcrypt_password` 方法；`plaintext_password` 永不过期。

<Note>
  日期时间字符串由 `parseDateTimeBestEffort` 解析，该函数仅识别时区标记 `UTC`、`GMT`、`Z`、`MSK`、`MSD`，以及 `+09:00` 或 `-05:00` 等数值偏移量。不支持 `Asia/Tokyo` 或 `Europe/London` 这类命名 IANA 时区；对于采用夏令时的区域，固定偏移量并不等同于 IANA 时区，因此必须根据要编码的具体日期计算正确的偏移量。
</Note>

<div id="valid-for-clause">
  ## VALID FOR 子句
</div>

`VALID FOR` 子句是 `VALID UNTIL` 的便捷简写。它不使用绝对日期和时间，而是接受一个[时间间隔](/zh/reference/data-types/special-data-types/interval)，并在执行查询时将过期截止时间计算为当前时间加上该时间间隔。结果随后以 `VALID UNTIL` 形式存储，因此 `SHOW CREATE USER` 始终显示解析出的绝对截止时间。它可在任何可使用 `VALID UNTIL` 的位置使用，并遵循相同的放置规则：位于 `IDENTIFIED` 之前 (或未指定身份验证方法时) 时，它是适用于所有方法的用户级截止时间；位于某个身份验证方法之后时，则仅适用于该方法。截止时间以秒级精度存储和强制执行，因此不接受亚秒级时间间隔 (`NANOSECOND`、`MICROSECOND`、`MILLISECOND`) ；可接受的最小单位为 `SECOND`。负时间间隔可用于将凭据标记为已过期；如果计算得到的截止时间早于 `1970-01-01 00:00:01 UTC`，则会将其规范化为该最早的过期时刻，之后 `SHOW CREATE USER` 将报告该时刻——如 [`VALID UNTIL`](#valid-until-clause) 所述，它会以服务器或会话时区显示。

示例：

* `CREATE USER name1 VALID FOR INTERVAL 1 DAY`
* `CREATE USER name1 VALID FOR INTERVAL 3 MONTH`
* `CREATE USER name1 VALID FOR INTERVAL 1 DAY + INTERVAL 12 HOUR`
* `CREATE USER name1 VALID FOR INTERVAL 30 DAY IDENTIFIED WITH plaintext_password BY 'password_1', bcrypt_password BY 'password_2'` — 用户级截止时间适用于这两种方法。
* `CREATE USER name1 IDENTIFIED WITH plaintext_password BY 'no_expiration', bcrypt_password BY 'expiration_set' VALID FOR INTERVAL 30 DAY` — 截止时间仅适用于 `bcrypt_password` 方法；`plaintext_password` 永不过期。

<div id="grants-clause">
  ## GRANTS 子句
</div>

可限制通过特定身份验证方法登录的会话所拥有的访问权限。该子句接受一个用括号括起的特权列表，其格式与 [GRANT](/zh/reference/statements/grant) 语句相同。它应指定在身份验证方法之后 (如有 `VALID UNTIL` 子句，则位于其后) ，且仅适用于该方法。

当用户通过此类身份验证方法登录时，会话的访问权限是用户访问权限 (包括已获授角色的权限) 与子句中列出特权的交集。该子句绝不会增加任何访问权限：如果列出的特权未授予该用户，会话便不具备该特权。通过此类方法进行身份验证的会话也不能授予特权 (`GRANT OPTION` 永远不会保留在交集中) ，也不能管理角色。管理角色不仅包括创建、修改、删除、授予和撤销角色，还包括更改默认情况下为用户激活的角色 (`SET DEFAULT ROLE` 和 `ALTER USER ... DEFAULT ROLE`) ；这些操作同样会被拒绝。

`EXECUTE AS` 会切换会话的主体，因此，以模拟身份运行的语句受**目标**用户访问权限与所列特权交集的限制，而非登录用户的权限限制。该限制本身永远不会解除；此外，模拟身份要求 `IMPERSONATE ON target` 同时已授予该用户并列在子句中。因此，受限凭据的权限范围绝不会超过同一用户的不受限凭据。

这为应用程序创建标记提供了一种便捷方式：创建一个绑定到该用户、具有到期日期和有限特权集的额外凭据。它会在 `system.query_log` 和 `system.processes` 中显示为该用户；用户被删除后便无法再使用；用户失去访问权限时，它也会失去相应权限。

<Warning>
  **仅在发起节点强制执行。** 身份验证方法的 `GRANTS` 限制及其 `VALID UNTIL` 到期时间仅在接收查询的节点 (发起节点) 上强制执行。它们**不会**传播到集群中的其他节点，因此请勿依赖该子句在集群级别限制执行。远程节点仍保留其通常的角色作用域。该子句在 `users.xml` 中也不可用。[查询结果缓存](/zh/concepts/features/performance/caches/query-cache)由同一用户的所有身份验证方法共享：它按用户和角色隔离缓存条目，且缓存命中时不会根据会话登录所用方法的 `GRANTS` 重新检查。
</Warning>

示例：

* `CREATE USER name1 IDENTIFIED BY 'qwerty' GRANTS (SELECT ON db.*)`
* `ALTER USER name1 ADD IDENTIFIED WITH plaintext_password BY 'app_token' VALID UNTIL '2026-12-31' GRANTS (SELECT ON db.table, INSERT ON db.table)`

请注意，该限制是身份验证方法的属性，并在登录时确定：使用 `ALTER USER` 更改子句只会影响新会话，不会影响已建立的会话。

该子句暂不支持带过滤器的源授权，例如 `READ ON S3('s3://bucket/.*')`：交集会将源过滤器视为不透明字符串进行比较，无法将一个过滤器缩小为另一个过滤器，因此此类授权会被拒绝，而不会静默地导致不授予任何访问权限。

该子句仅支持凭据完全由服务器本地验证的身份验证方法。对于验证时会联系外部系统的方法 (对于 `jwt`，则可能会联系外部系统，例如获取签名密钥)  (`ldap`、`kerberos`、`http`、`jwt`) ，该子句会被拒绝：当多个身份验证方法接受同一凭据时，限制通过根据其他方法重新检查凭据来强制执行；额外探测外部系统并不安全，因此接受同一凭据的其他方法可能绕过该限制。

当同一有效凭据被多个身份验证方法接受时，登录会以故障关闭的方式受所有这些方法限制：会话获得所有匹配方法的 `GRANTS` 的交集，并在最早的 `VALID UNTIL` 时到期。即使最早的 `VALID UNTIL` 已经过期，它仍然优先：登录会被拒绝，就如同唯一匹配的方法已过期一样。因此，标记过期绝不会悄然使共享凭据获得更宽泛方法的权限或有效期。

出于同样的原因，此组合仅在由 服务器 本地验证的身份验证方法之间进行检查：如上所述，对于外部验证的方法，该子句本身会被拒绝，因为重新检查凭据需要对外部系统进行一次不安全的额外探测。因此，如果同一用户的外部验证方法 (`ldap`、`kerberos`、`http`、`jwt`) 恰好也接受相同的凭据，则该方法自身的 `VALID UNTIL` 不会纳入此组合，为其配置的较早到期时间也不会缩短通过本地验证方法获得的 会话。

<div id="grantees-clause">
  ## GRANTEES 子句
</div>

指定允许从该用户接收[权限](/zh/reference/statements/grant#privileges)的用户或角色，前提是该用户本身也已通过 [GRANT OPTION](/zh/reference/statements/grant#granting-privilege-syntax) 获得了所有必需的访问授权。`GRANTEES` 子句的选项包括：

* `user` — 指定该用户可以向其授予权限的用户。
* `role` — 指定该用户可以向其授予权限的角色。
* `ANY` — 该用户可以向任何人授予权限。这是默认设置。
* `NONE` — 该用户不能向任何人授予权限。

你可以使用 `EXCEPT` 表达式来排除任意用户或角色。例如，`CREATE USER user1 GRANTEES ANY EXCEPT user2`。这表示如果 `user1` 拥有某些通过 `GRANT OPTION` 授予的权限，它就能够将这些权限授予除 `user2` 之外的任何人。

<div id="examples">
  ## 示例
</div>

创建用户账户 `mira`，并使用密码 `qwerty` 进行保护：

```sql theme={null}
CREATE USER mira HOST IP '127.0.0.1' IDENTIFIED WITH sha256_password BY 'qwerty';
```

`mira` 应在运行 ClickHouse 服务器的主机上启动客户端应用程序。

创建用户账户 `john` 并分配角色：

```sql theme={null}
CREATE USER john ROLE role1, role2;
```

创建用户账户 `john`，分配角色，并将其中部分角色设为默认：

```sql theme={null}
CREATE USER john ROLE role1, role2 DEFAULT ROLE role1;
```

或

```sql theme={null}
CREATE USER john ROLE role1, role2 DEFAULT ROLE ALL EXCEPT role2;
```

创建用户账户 `john`，并允许他将自己的权限授予 `jack` 用户账户：

```sql theme={null}
CREATE USER john GRANTEES jack;
```

使用查询参数来创建用户账户 `john`：

```sql theme={null}
SET param_user=john;
CREATE USER {user:Identifier};
```
