创建用户

语法

CREATE [OR REPLACE] USER [IF NOT EXISTS] 
 user_specification [,user_specification ...] 
  [REQUIRE {NONE | tls_option [[AND] tls_option ...] }]
  [WITH resource_option [resource_option ...] ]
  [lock_option] [password_option] 

user_specification:
  username [authentication_option]

authentication_option:
  IDENTIFIED BY 'password' 
  | IDENTIFIED BY PASSWORD 'password_hash'
  | IDENTIFIED {VIA|WITH} authentication_rule [OR authentication_rule  ...]

authentication_rule:
    authentication_plugin
  | authentication_plugin {USING|AS} 'authentication_string'
  | authentication_plugin {USING|AS} PASSWORD('password')

tls_option:
  SSL 
  | X509
  | CIPHER 'cipher'
  | ISSUER 'issuer'
  | SUBJECT 'subject'

resource_option:
  MAX_QUERIES_PER_HOUR count
  | MAX_UPDATES_PER_HOUR count
  | MAX_CONNECTIONS_PER_HOUR count
  | MAX_USER_CONNECTIONS count
  | MAX_STATEMENT_TIME time

password_option:
  PASSWORD EXPIRE
  | PASSWORD EXPIRE DEFAULT
  | PASSWORD EXPIRE NEVER
  | PASSWORD EXPIRE INTERVAL N DAY

lock_option:
    ACCOUNT LOCK
  | ACCOUNT UNLOCK
}

描述

CREATE USER 语句创建新的 MariaDB 帐户。要使用它,您必须具有全局 CREATE USER 特权或 INSERT 特权以访问 mysql 数据库。对于每个帐户,CREATE USERmysql.user (在 MariaDB 10.3 之前是表,在 MariaDB 10.4 之后是视图) 或 mysql.global_priv_table (从 MariaDB 10.4 开始) 中创建一个没有权限的新行。

如果指定的任何帐户或指定的帐户的任何权限已经存在,则服务器将返回 ERROR 1396 (HY000)。如果发生错误,CREATE USER 仍将创建未产生错误的帐户。对于未创建的所有用户,只产生一个错误:

ERROR 1396 (HY000): 
  Operation CREATE USER failed for 'u1'@'%','u2'@'%'

CREATE USERDROP USERCREATE ROLEDROP ROLE 失败时,它们都会产生相同的错误代码。

有关指定帐户名称的详细信息,请参阅下面的 帐户名称

OR REPLACE

如果使用可选的 OR REPLACE 子句,则基本上是以下快捷方式:

DROP USER IF EXISTS name;
CREATE USER name ...;

例如:

CREATE USER foo2@test IDENTIFIED BY 'password';
ERROR 1396 (HY000): Operation CREATE USER failed for 'foo2'@'test'

CREATE OR REPLACE USER foo2@test IDENTIFIED BY 'password';
Query OK, 0 rows affected (0.00 sec)

IF NOT EXISTS

当使用 IF NOT EXISTS 子句时,如果指定的用户已经存在,则 MariaDB 将返回一个警告而不是错误。

例如:

CREATE USER foo2@test IDENTIFIED BY 'password';
ERROR 1396 (HY000): Operation CREATE USER failed for 'foo2'@'test'

CREATE USER IF NOT EXISTS foo2@test IDENTIFIED BY 'password';
Query OK, 0 rows affected, 1 warning (0.00 sec)

显示警告;
+-------+------+----------------------------------------------------+
| Level | Code | Message                                            |
+-------+------+----------------------------------------------------+
| Note  | 1973 | Can't create user 'foo2'@'test'; it already exists |
+-------+------+----------------------------------------------------+

认证选项

IDENTIFIED BY 'password'

可选的 IDENTIFIED BY 子句可用于为帐户提供密码。密码应以明文形式指定。在存储在 mysql.user/mysql.global_priv_table 表中之前,它将由 PASSWORD 函数进行哈希处理。

例如,如果我们的密码是 mariadb,则可以使用以下命令创建用户:

CREATE USER foo2@test IDENTIFIED BY 'mariadb';

如果您没有在 IDENTIFIED BY 子句中指定密码,则该用户将能够无密码连接。空白密码不是匹配任何密码的通配符。如果没有设置密码,则用户必须在不提供密码的情况下连接。

此子句支持的唯一 认证插件mysql_native_passwordmysql_old_password

IDENTIFIED BY PASSWORD 'password_hash'

可选的 IDENTIFIED BY PASSWORD 子句可用于提供已经被哈希处理的密码的帐户。密码应指定为由 PASSWORD 函数提供的哈希值。它将按原样存储在 mysql.user/mysql.global_priv_table 表中。

例如,如果我们的密码是 mariadb,则可以使用以下命令查找哈希值:

SELECT PASSWORD('mariadb');
+-------------------------------------------+
| PASSWORD('mariadb')                       |
+-------------------------------------------+
| *54958E764CE10E50764C2EECBB71D01F08549980 |
+-------------------------------------------+
1 row in set (0.00 sec)

然后,我们可以使用哈希值创建用户:

CREATE USER foo2@test IDENTIFIED BY PASSWORD '*54958E764CE10E50764C2EECBB71D01F08549980';

如果您没有在 IDENTIFIED BY 子句中指定密码,则该用户将能够无密码连接。空白密码不是匹配任何密码的通配符。如果没有设置密码,则用户必须在不提供密码的情况下连接。

这个子句支持的唯一认证插件mysql_native_passwordmysql_old_password

通过认证插件认证

可选的IDENTIFIED VIA认证插件允许您指定帐户应由特定的认证插件进行身份验证。插件名称必须是作为SHOW PLUGINS的活动认证插件。如果它没有显示在该输出中,则需要使用INSTALL PLUGININSTALL SONAME安装它。

例如,这可以与PAM认证插件一起使用:

CREATE USER foo2@test IDENTIFIED VIA pam;

某些认证插件允许在USING或AS关键字之后指定其他参数。例如,PAM认证插件接受服务名称:

CREATE USER foo2@test IDENTIFIED VIA pam USING 'mariadb';

附加参数的确切含义取决于特定的认证插件。

MariaDB starting with 10.4.0

如果作为PASSWORD()函数的参数提供了明文密码,则可以使用USINGAS关键字将纯文本密码提供给插件。这仅适用于已实现PASSWORD()函数钩子的认证插件。例如,ed25519认证插件支持此操作:

CREATE USER safe@'%' IDENTIFIED VIA ed25519 USING PASSWORD('secret');
MariaDB starting with 10.4.3

可以指定多个认证插件,它们都可以作为用户身份验证的替代方式:

CREATE USER safe@'%' IDENTIFIED VIA ed25519 USING PASSWORD('secret') OR unix_socket;

默认情况下,当您创建一个没有指定认证插件的用户时,MariaDB使用mysql_native_password插件。

TLS 选项

默认情况下,MariaDB在服务器和客户端之间传输数据时不加密。当服务器和客户端在同一主机上运行或在通过其他方式保证安全性的网络中运行时,这通常是可以接受的。但是,在服务器和客户端存在于不同网络或它们在高风险网络中的情况下,缺乏加密确实会引入安全问题,因为恶意行为者有可能窃听它们之间在网络上传输的流量。

为了缓解这个问题,MariaDB允许您使用传输层安全性(TLS)协议在服务器和客户端之间加密传输的数据。TLS以前称为安全套接字层(SSL),但严格来说SSL协议是TLS的前身,并且该协议的版本现在被认为是不安全的。文档仍经常使用术语SSL,出于兼容性原因,与TLS相关的服务器系统和状态变量仍使用前缀ssl_,但在内部,MariaDB仅支持其安全的后继者。

有关如何确定您的MariaDB服务器是否具有TLS支持的更多信息,请参见Secure Connections Overview

您可以为特定用户帐户设置某些与TLS相关的限制。例如,您可能会将其用于需要访问敏感数据的用户帐户,同时将其发送到您无法控制的网络。可以使用CREATE USERALTER USERGRANT语句为用户帐户启用这些限制。以下选项可用:

选项描述
REQUIRE NONE此账户不需要使用 TLS,但仍可使用。
REQUIRE SSL此账户必须使用 TLS,但不需要有效的 X509 证书。此选项不能与其他 TLS 选项组合使用。
REQUIRE X509此账户必须使用 TLS,并且必须具有有效的 X509 证书。此选项意味着 REQUIRE SSL。此选项不能与其他 TLS 选项组合使用。
REQUIRE ISSUER 'issuer'此账户必须使用 TLS,并且必须具有有效的 X509 证书。此外,证书颁发机构必须是通过字符串 issuer 指定的那个。此选项意味着 REQUIRE X509。此选项可以与 SUBJECTCIPHER 选项以任意顺序组合使用。
REQUIRE SUBJECT 'subject'此账户必须使用 TLS,并且必须具有有效的 X509 证书。此外,证书的主题必须是通过字符串 subject 指定的那个。此选项意味着 REQUIRE X509。此选项可以与 ISSUERCIPHER 选项以任意顺序组合使用。
REQUIRE CIPHER 'cipher'此账户必须使用 TLS,但不需要有效的 X509 证书。此外,连接所使用的加密必须使用字符串 cipher 中指定的特定密码方法。此选项意味着 REQUIRE SSL。此选项可以与 ISSUERSUBJECT 选项以任意顺序组合使用。

REQUIRE 关键字必须仅用于指定选项的一次,而 AND 关键字可用于分隔单个选项,但不是必需的。

例如,您可以创建一个需要以下 TLS 选项的用户帐户:

CREATE USER 'alice'@'%'
 REQUIRE SUBJECT '/CN=alice/O=My Dom, Inc./C=US/ST=Oregon/L=Portland'
 AND ISSUER '/C=FI/ST=Somewhere/L=City/ O=Some Company/CN=Peter Parker/[email protected]'
 AND CIPHER 'SHA-DES-CBC3-EDH-RSA';

如果为特定用户帐户设置了这些选项中的任何一个,则尝试使用该用户帐户连接的任何客户端都必须配置为使用 TLS 连接。

有关如何在客户端和服务器上启用 TLS 的信息,请参见 Securing Connections for Client and Server

资源限制选项

可以为某些服务器资源设置每个帐户的限制。下表显示了每个帐户可以设置的值:

限制类型描述
MAX_QUERIES_PER_HOUR帐户每小时可以发出的语句数量(包括更新)
MAX_UPDATES_PER_HOUR帐户每小时可以发出的更新(而不是查询)数量
MAX_CONNECTIONS_PER_HOUR帐户每小时可以启动的连接数量
MAX_USER_CONNECTIONS可以从同一帐户接受的同时连接数;如果为 0,则将使用 max_connections;如果 max_connections 为 0,则此帐户的同时连接没有限制。
MAX_STATEMENT_TIME用户执行的语句的超时时间(以秒为单位)。另请参见 Aborting Statements that Exceed a Certain Time to Execute

如果将这些限制中的任何一个设置为 0,则该用户的该资源没有限制。

以下是创建具有资源限制的用户的示例:

CREATE USER 'someone'@'localhost' WITH
    MAX_USER_CONNECTIONS 10
    MAX_QUERIES_PER_HOUR 200;

这些资源按帐户跟踪,这意味着 'user'@'server';而不是按用户名或连接计数。

可以使用 FLUSH USER_RESOURCESFLUSH PRIVILEGESmysqladmin reload 重置所有用户的计数。

每个帐户的资源限制存储在 mysql 数据库中的 user 表中。用于资源限制的列名为 max_questionsmax_updatesmax_connectionsMAX_CONNECTIONS_PER_HOUR 的别名)和 max_user_connectionsMAX_USER_CONNECTIONS 的别名)。

帐户名称

帐户名称由用户名组件和主机名组件组成,并指定为'user_name'@'host_name'

用户名和主机名可以不加引号,也可以使用双引号(")或单引号(')作为字符串引用,或使用反引号(`)作为标识符引用。在使用特殊字符(如连字符)或通配符字符时必须使用引号。如果使用引号,则必须分别引用用户名和主机名(例如'user_name'@'host_name')。

主机名组件

如果未提供主机名,则假定为“%”

主机名可以包含通配符字符 %_。它们与 LIKE 子句一样匹配。如果需要字面匹配通配符字符(例如匹配带有下划线的域名),请在字符前加上反斜杠。有关转义通配符字符的更多信息,请参见 LIKE

主机名匹配不区分大小写。主机名可以匹配域名或 IP 地址。使用 localhost 作为主机名,仅允许本地客户端连接。在 Linux 上,回环接口(127.0.0.1)不会将“localhost”视为本地连接:这意味着仅通过 UNIX 域套接字连接才会匹配“localhost”。

您可以使用网络掩码来匹配一系列 IP 地址,使用“base_ip/netmask”作为主机名。如果用户具有 IP 地址 ip_addr,则如果满足以下条件,将允许连接:

ip_addr & netmask = base_ip

例如,给定用户:

CREATE USER 'maria'@'247.150.130.0/255.255.255.0';

满足此条件的 IP 地址范围从 247.150.130.0 到 247.150.130.255。

使用 255.255.255.255 等效于根本不使用网络掩码。IPv6 地址不能使用网络掩码。

请注意,在使用“%”通配符主机创建用户时添加的凭据并不总是授予访问权限。例如,某些系统带有匿名本地主机用户,在从本地主机连接时,这将优先考虑。

MariaDB 10.6 之前,主机名组件最长可达 60 个字符。从 MariaDB 10.6 开始,它可以达到 255 个字符。

用户名组件

用户名必须完全匹配,包括大小写。空用户名称为空白帐户,并允许与任何用户名组件匹配的登录尝试。这些将在下一节中更详细地描述。

有关用作用户名的有效标识符,请参见标识符名称

有可能在用户连接时匹配多个帐户。MariaDB 根据以下标准排序后选择第一个匹配的帐户:

  • 具有精确主机名的帐户在使用主机名中的通配符之前排序。使用网络掩码的主机名被视为排序时是精确的。
  • 具有主机名中的通配符的帐户根据第一个通配符字符的位置排序。具有较晚通配符字符的主机名排在具有较早通配符字符的主机名之前。
  • 具有非空用户名的帐户在具有空用户名的帐户之前排序。
  • 具有空用户名的帐户最后排序。如前所述,这些称为匿名帐户。这些将在下一节中更详细地描述。

以下表格显示了按这些标准排序的示例帐户:

+---------+-------------+
| User    | Host        |
+---------+-------------+
| joffrey | 192.168.0.3 |
|         | 192.168.0.% |
| joffrey | 192.168.%   |
|         | 192.168.%   |
+---------+-------------+

一旦连接成功,您只能获得与匹配的帐户授予的特权,而不是所有可能匹配的帐户。例如,考虑以下命令:

CREATE USER 'joffrey'@'192.168.0.3';
CREATE USER 'joffrey'@'%';
GRANT SELECT ON test.t1 to 'joffrey'@'192.168.0.3';
GRANT SELECT ON test.t2 to 'joffrey'@'%';

如果您从 192.168.0.3 连接为 joffrey,则对于表 test.t1,您将具有 SELECT 特权,但对于表 test.t2,您将没有特权。如果您从任何其他 IP 地址连接为 joffrey,则对于表 test.t2,您将具有 SELECT 特权,但对于表 test.t1,您将没有特权。

在 10.6 之前,用户名可以长达 80 个字符,在 10.6 及之后,它可以长达 128 个字符。

匿名帐户

匿名帐户是指帐户名称的用户名部分为空的帐户。这些帐户充当特殊的捕获所有帐户。如果用户尝试从主机登录系统,并且存在一个匿名帐户,其主机名部分与用户的主机相匹配,则如果没有更具体的帐户匹配用户输入的用户名,则用户将作为匿名帐户登录。

例如,以下是一些匿名帐户:

CREATE USER ''@'localhost';
CREATE USER ''@'192.168.0.3';

修复一个遗留的默认匿名账户

在某些系统上,mysql.db 表中默认情况下有一些 ''@'%' 匿名帐户条目。不幸的是,在 mysql.user/mysql.global_priv_table 表中没有匹配的条目,这意味着这个匿名帐户不存在,但是它确实具有特权 - 通常是在由 mysql_install_db 创建的默认 test 数据库上。这些无账户特权是MySQL权限系统不太先进时留下的遗产。

这种情况意味着如果您尝试创建一个 ''@'%' 帐户,则会遇到错误。例如:

CREATE USER ''@'%';
ERROR 1396 (HY000): Operation CREATE USER failed for ''@'%'

修复方法是DELETE mysql.db 表中的行,然后执行FLUSH PRIVILEGES

DELETE FROM mysql.db WHERE User='' AND Host='%';
FLUSH PRIVILEGES;

然后可以创建用户账户:

CREATE USER ''@'%';
Query OK, 0 rows affected (0.01 sec)

有关更多信息,请参见 MDEV-13486

密码过期

MariaDB starting with 10.4.3

除了根据 default_password_lifetime 自动过期密码之外,还可以在个别用户的基础上设置密码过期时间,覆盖全局设置,例如:

CREATE USER 'monty'@'localhost' PASSWORD EXPIRE INTERVAL 120 DAY;

有关更多详细信息,请参见 用户密码过期

账户锁定

MariaDB starting with 10.4.2

账户锁定允许特权管理员锁定 / 解锁用户账户。如果已锁定账户,则不允许新的客户端连接(现有连接不受影响)。例如:

CREATE USER 'marijn'@'localhost' ACCOUNT LOCK;

有关更多详细信息,请参见账户锁定

MariaDB 10.4.7MariaDB 10.5.8 开始,lock_optionpassword_option 子句可以以任意顺序出现。

参见

Comments

Comments loading...
Content reproduced on this site is the property of its respective owners, and this content is not reviewed in advance by MariaDB. The views, information and opinions expressed by this content do not necessarily represent those of MariaDB or any other party.