13.7.1.4 GRANT 声明
GRANT
priv_type [(column_list)]
[, priv_type [(column_list)]] ...
ON [object_type] priv_level
TO user [auth_option] [, user [auth_option]] ...
[REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
[WITH {GRANT OPTION | resource_option} ...]
GRANT PROXY ON user
TO user [, user] ...
[WITH GRANT OPTION]
object_type: {
TABLE
| FUNCTION
| PROCEDURE
}
priv_level: {
*
| *.*
| db_name.*
| db_name.tbl_name
| tbl_name
| db_name.routine_name
}
user:
(see Section6.2.4, "Specifying Account Names")
auth_option: {
IDENTIFIED BY 'auth_string'
| IDENTIFIED WITH auth_plugin
| IDENTIFIED WITH auth_plugin BY 'auth_string'
| IDENTIFIED WITH auth_plugin AS 'auth_string'
| IDENTIFIED BY PASSWORD 'auth_string'
}
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
}
GRANT语句向 MySQL 用户帐户授予特权。 GRANT语句有多个方面,在以下主题下进行了介绍:
GRANT 概述
GRANT语句向 MySQL 用户帐户授予特权。
要使用GRANT授予特权,您必须具有GRANT OPTION特权,并且您必须具有要授予的特权。 (或者,如果您对mysql
系统数据库中的授予 table 具有UPDATE特权,则可以向任何帐户授予任何特权。)启用read_only系统变量时,GRANT还需要SUPER特权。
REVOKE语句与GRANT相关,并使 Management 员可以删除帐户特权。参见第 13.7.1.6 节“ REVOKE 语句”。
每个帐户名称都使用第 6.2.4 节“指定帐户名”中描述的格式。例如:
GRANT ALL ON db1.* TO 'jeffrey'@'localhost';
帐户的主机名部分(如果省略)默认为'%'
。
通常,数据库 Management 员首先使用CREATE USER创建一个帐户并定义其非特权 Feature,例如其密码,是否使用安全连接以及对服务器资源的访问限制,然后使用GRANT定义其特权。 ALTER USER可用于更改现有帐户的非特权 Feature。例如:
CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'password';
GRANT ALL ON db1.* TO 'jeffrey'@'localhost';
GRANT SELECT ON db2.invoice TO 'jeffrey'@'localhost';
ALTER USER 'jeffrey'@'localhost' WITH MAX_QUERIES_PER_HOUR 90;
Note
此处显示的示例不包含IDENTIFIED
子句。假定您在创建帐户时使用CREATE USER设置密码,以避免创建不安全的帐户。
Note
如果在GRANT语句中命名的帐户尚不存在,则GRANT可以在稍后讨论NO_AUTO_CREATE_USER SQL 模式的条件下创建该帐户。也可以使用GRANT指定非特权帐户 Feature,例如是否使用安全连接以及对服务器资源的访问限制。
但是,自 MySQL 5.7.6 起,不建议使用GRANT来创建帐户或定义非特权 Feature。而是使用CREATE USER或ALTER USER执行这些任务。
在mysql程序中,成功执行GRANT时以Query OK, 0 rows affected
响应。要确定该操作会带来哪些特权,请使用SHOW GRANTS。参见第 13.7.5.21 节“ SHOW GRANTS 语句”。
Important
在某些情况下,GRANT可能会记录在服务器日志中或 Client 端的历史记录文件(例如~/.mysql_history
)中,这意味着任何具有对该信息的读取权限的人都可以读取明文密码。有关服务器日志发生这种情况的条件以及如何控制它的信息,请参阅第 6.1.2.3 节“密码和日志记录”。有关 Client 端日志记录的类似信息,请参见第 4.5.1.3 节“ mysqlClient 端记录”。
GRANT支持最多 60 个字符的主机名。用户名最多可以包含 32 个字符。数据库,table,列和例程的名称最多可以包含 64 个字符。
Warning
请勿尝试通过更改mysql.user
系统 table 来更改用户名的允许长度。这样做会导致无法预测的行为,甚至可能使用户无法登录到 MySQL 服务器。除通过第 2.11 节“升级 MySQL”中描述的过程外,切勿以任何方式更改mysql
系统数据库中 table 的结构。
对象引用准则
GRANT语句中的多个对象均需加引号,尽管在许多情况下引号是可选的:帐户,数据库,table,列和例程名称。例如,如果帐户名中的* user_name
或 host_name
值作为未加引号的标识符是合法的,则无需使用引号。但是,必须使用引号来指定包含特殊字符(例如-
)的 user_name
字符串或包含特殊字符或例如%
的通配符(例如'test-user'@'%.com'
)的 host_name
*字符串。分别引用用户名和主机名。
要指定引用的值:
-
引用数据库,table,列和例程名称作为标识符。
-
用用户名和主机名加引号作为标识符或字符串。
-
用密码引用字符串。
有关字符串引用和标识符引用的准则,请参见第 9.1.1 节“字符串 Literals”和第 9.2 节“架构对象名称”。
在GRANT语句中指定数据库名称以在数据库级别(GRANT ... ON db_name.*
)授予特权时,允许使用_
和%
通配符。例如,这意味着要将_
字符用作数据库名称的一部分,请在GRANT语句中将其指定为\_
,以防止用户能够访问与通配符模式匹配的其他数据库(例如,) )。
如果不使用数据库名称在数据库级别授予特权,而是将其用作授予 table 或例程(例如GRANT ... ON db_name.tbl_name
)之类的其他对象的特权的限定符,则通配符将被视为普通字符。
MySQL 支持的特权
下 table 总结了可以为GRANT和REVOKE语句指定的* priv_type
*特权类型,以及可以授予每个特权的级别。有关每种特权的更多信息,请参见第 6.2.2 节“ MySQL 提供的特权”。
table13.8 授予和撤销的许可特权
Privilege | 含义和授予级别 |
---|---|
ALL [PRIVILEGES] | 授予除GRANT OPTION和PROXY之外的指定访问级别的所有特权。 |
ALTER | 启用ALTER TABLE的使用。级别:全局,数据库,table。 |
ALTER ROUTINE | 使存储的例程能够被更改或删除。级别:全局,数据库,常规。 |
CREATE | 启用数据库和 table 创建。级别:全局,数据库,table。 |
CREATE ROUTINE | 启用存储的例程创建。级别:全局,数据库。 |
CREATE TABLESPACE | 启用 table 空间和日志文件组的创建,更改或删除。级别:Global。 |
创建临时 table | 启用创建临时 table的使用。级别:全局,数据库。 |
CREATE USER | 启用CREATE USER,DROP USER,RENAME USER和撤销所有特权的使用。级别:Global。 |
CREATE VIEW | 启用视图的创建或更改。级别:全局,数据库,table。 |
DELETE | 启用DELETE的使用。级别:全局,数据库,table。 |
DROP | 启用要删除的数据库,table 和视图。级别:全局,数据库,table。 |
EVENT | 为事件计划程序启用事件的使用。级别:全局,数据库。 |
EXECUTE | 使用户能够执行存储的例程。级别:全局,数据库,常规。 |
FILE | 使用户能够使服务器读取或写入文件。级别:Global。 |
GRANT OPTION | 启用授予其他帐户特权或从其他帐户删除的特权。级别:全局,数据库,table,例程,代理。 |
INDEX | 启用要创建或删除的索引。级别:全局,数据库,table。 |
INSERT | 启用INSERT的使用。级别:全局,数据库,table,列。 |
LOCK TABLES | 在具有SELECT特权的 table 上启用LOCK TABLES的使用。级别:全局,数据库。 |
PROCESS | 使用户能够使用SHOW PROCESSLIST查看所有进程。级别:Global。 |
PROXY | 启用用户代理。级别:从一个用户到另一个用户。 |
REFERENCES | 启用外键创建。级别:全局,数据库,table,列。 |
RELOAD | 启用使用FLUSH操作。级别:Global。 |
REPLICATION CLIENT | 使用户能够询问源服务器或副本服务器在哪里。级别:Global。 |
REPLICATION SLAVE | 使副本能够从源读取二进制日志事件。级别:Global。 |
SELECT | 启用SELECT的使用。级别:全局,数据库,table,列。 |
SHOW DATABASES | 启用SHOW DATABASES以显示所有数据库。级别:Global。 |
SHOW VIEW | 启用显示创建视图的使用。级别:全局,数据库,table。 |
SHUTDOWN | 启用mysqladmin shutdown的使用。级别:Global。 |
SUPER | 启用其他 Management 操作的使用,例如更改为主,KILL,清除二进制日志,SET GLOBAL和mysqladmin debug命令。级别:Global。 |
TRIGGER | 启用触发器操作。级别:全局,数据库,table。 |
UPDATE | 启用UPDATE的使用。级别:全局,数据库,table,列。 |
USAGE | “没有特权”的同义词 |
触发器与 table 关联。要创建或删除触发器,您必须具有 table 的TRIGGER特权,而不是触发器。
在GRANT语句中,必须自己命名ALL [PRIVILEGES]或PROXY特权,并且不能与其他特权一起指定。 ALL [PRIVILEGES]代 table 授予特权级别的所有可用特权,但GRANT OPTION和PROXY特权除外。
可以指定USAGE来创建没有特权的用户,或者为帐户指定REQUIRE
或WITH
子句而不更改其现有特权。 (但是,不建议使用GRANT来定义非特权 Feature。
MySQL 帐户信息存储在mysql
系统数据库的 table 中。有关其他详细信息,请查阅第 6.2 节“访问控制和帐户 Management”,该文章广泛讨论mysql
系统数据库和访问控制系统。
如果授予 table 包含包含大小写混合的数据库或 table 名的特权行,并且lower_case_table_names系统变量设置为非零值,则不能使用REVOKE撤消这些特权。有必要直接操作授权 table。 (设置lower_case_table_names时GRANT不会创建此类行,但是此类行可能是在设置该变量之前创建的。)
可以在多个级别上授予特权,具体取决于ON
子句使用的语法。对于REVOKE,相同的ON
语法指定要删除的特权。
对于全局,数据库,table 和例行级别,GRANT ALL仅分配要授予的级别上存在的特权。例如,GRANT ALL ON db_name.*
是数据库级别的语句,因此它不授予任何仅全局特权,例如FILE。授予ALL不会分配GRANT OPTION或PROXY特权。
如果以下对象是 table,存储函数或存储过程,则* object_type
*子句(如果存在)应指定为TABLE
,FUNCTION
或PROCEDURE
。
用户为数据库,table,列或例程持有的特权是作为每个特权级别(包括全局级别)的帐户特权的逻辑OR形成的。无法通过在较低级别上缺少该特权来拒绝在较高级别上授予的特权。例如,以下语句全局授予SELECT和INSERT特权:
GRANT SELECT, INSERT ON *.* TO u1;
全局授予的特权适用于所有数据库,table 和列,即使未在任何较低级别上授予。
第 6.2.6 节“访问控制,第 2 阶段:请求验证”中提供了特权检查过程的详细信息。
如果您甚至为一个用户使用 table,列或例程特权,服务器将检查所有用户的 table,列和例程特权,这会使 MySQL 变慢。同样,如果您限制任何用户的查询,更新或连接数,则服务器必须监视这些值。
MySQL 使您可以授予不存在的数据库或 table 的特权。对于 table,要授予的特权必须包括CREATE特权。 此行为是设计使然,旨在使数据库 Management 员能够为稍后创建的数据库或 table 准备用户帐户和特权。
Important
当您删除数据库或 table 时,MySQL 不会自动取消任何特权。但是,如果删除例程,则为该例程授予的任何例程级特权都将被吊销。
帐户名和密码
GRANT语句中的* user
值 table 示该语句适用的 MySQL 帐户。为了适应从任意主机向用户授予权限,MySQL 支持以'user_name'@'host_name'
形式指定 user
*值。
您可以在主机名中指定通配符。例如,对于example.com
域中的任何主机,'user_name'@'%.example.com'
适用于* user_name
,对于198.51.100
C 类子网中的任何主机,'user_name'@'198.51.100.%'
适用于 user_name
*。
简单形式'user_name'
是'user_name'@'%'
的同义词。
- MySQL 不支持用户名中的通配符*。要引用匿名用户,请使用GRANT语句指定一个用户名为空的帐户:
GRANT ALL ON test.* TO ''@'localhost' ...;
在这种情况下,将使用与匿名用户帐户相关联的特权,允许使用正确的匿名用户密码从 localhost 连接的任何用户访问。
有关帐户名中用户名和主机名值的其他信息,请参阅第 6.2.4 节“指定帐户名”。
Warning
如果允许本地匿名用户连接到 MySQL 服务器,则还应将所有本地用户的特权授予'user_name'@'localhost'
。否则,当命名用户尝试从本地计算机登录 MySQL 服务器时,将使用mysql.user
系统 table 中localhost
的匿名用户帐户。有关详细信息,请参见第 6.2.5 节“访问控制,第 1 阶段:连接验证”。
要确定此问题是否适用于您,请执行以下查询,其中列出了所有匿名用户:
SELECT Host, User FROM mysql.user WHERE User='';
为避免上述问题,请使用以下语句删除本地匿名用户帐户:
DROP USER ''@'localhost';
对于允许* auth_option
值跟随 user
值的GRANT语法, auth_option
*以IDENTIFIED
开头,并通过指定帐户身份验证插件,凭据(例如密码)或两者来指示帐户的身份验证。 * auth_option
*子句的语法与CREATE USER语句的语法相同。有关详细信息,请参见第 13.7.1.2 节“ CREATE USER 语句”。
Note
从 MySQL 5.7.6 开始,不再使用GRANT定义帐户身份验证 Feature。而是使用CREATE USER或ALTER USER构建或更改身份验证 Feature。 GRANT功能将在将来的 MySQL 版本中删除。
如果存在IDENTIFIED
并且您具有全局授予特权(GRANT OPTION),则指定的任何密码都将成为该帐户的新密码,即使该帐户存在并且已经具有密码。如果没有IDENTIFIED
,则帐户密码保持不变。
Global Privileges
全局特权是 Management 性的,或适用于给定服务器上的所有数据库。要分配全局特权,请使用ON *.*
语法:
GRANT ALL ON *.* TO 'someuser'@'somehost';
GRANT SELECT, INSERT ON *.* TO 'someuser'@'somehost';
CREATE TABLESPACE,CREATE USER,FILE,PROCESS,RELOAD,REPLICATION CLIENT,REPLICATION SLAVE,SHOW DATABASES,SHUTDOWN和SUPER特权是 Management 特权,只能在全局范围内授予。
其他特权可以全局授予,也可以在更特定的级别授予。
在全局级别授予任何全局特权的GRANT OPTION适用于所有全局特权。
MySQL 将全局特权存储在mysql.user
系统 table 中。
Database Privileges
数据库特权适用于给定数据库中的所有对象。要分配数据库级特权,请使用ON db_name.*
语法:
GRANT ALL ON mydb.* TO 'someuser'@'somehost';
GRANT SELECT, INSERT ON mydb.* TO 'someuser'@'somehost';
如果使用ON *
语法(而不是ON *.*
),则会在数据库级别为默认数据库分配特权。如果没有默认数据库,则会发生错误。
可以在数据库级别指定CREATE,DROP,EVENT,GRANT OPTION,LOCK TABLES和REFERENCES特权。table 或例程特权也可以在数据库级别指定,在这种情况下,它们适用于数据库中的所有 table 或例程。
MySQL 将数据库特权存储在mysql.db
系统 table 中。
Table Privileges
table 特权适用于给定 table 中的所有列。要分配 table 级特权,请使用ON db_name.tbl_name
语法:
GRANT ALL ON mydb.mytbl TO 'someuser'@'somehost';
GRANT SELECT, INSERT ON mydb.mytbl TO 'someuser'@'somehost';
如果指定* tbl_name
而不是 db_name.tbl_name
,则该语句适用于默认数据库中的 tbl_name
*。如果没有默认数据库,则会发生错误。
table 级别允许的* priv_type
*值为ALTER,CREATE VIEW,CREATE,DELETE,DROP,GRANT OPTION,INDEX,INSERT,REFERENCES,SELECT,SHOW VIEW,TRIGGER和UPDATE。
table 级特权适用于基本 table 和视图。它们不适用于使用创建临时 table创建的 table,即使 table 名匹配也是如此。有关TEMPORARY
table 特权的信息,请参见第 13.1.18.2 节“ CREATE TEMPORARY TABLE 语句”。
MySQL 将 table 特权存储在mysql.tables_priv
系统 table 中。
Column Privileges
列特权适用于给定 table 中的单个列。在列级别要授予的每个特权都必须在括号后加上一个或多个列。
GRANT SELECT (col1), INSERT (col1, col2) ON mydb.mytbl TO 'someuser'@'somehost';
列(即,当您使用* column_list
子句时)允许的 priv_type
*值为INSERT,REFERENCES,SELECT和UPDATE。
MySQL 将列特权存储在mysql.columns_priv
系统 table 中。
存储的常规特权
ALTER ROUTINE,CREATE ROUTINE,EXECUTE和GRANT OPTION特权适用于存储的例程(过程和函数)。可以在全局和数据库级别授予它们。除了CREATE ROUTINE之外,可以在例程级别为单个例程授予这些特权。
GRANT CREATE ROUTINE ON mydb.* TO 'someuser'@'somehost';
GRANT EXECUTE ON PROCEDURE mydb.myproc TO 'someuser'@'somehost';
在例程级别允许的priv_type
*值为ALTER ROUTINE,EXECUTE和GRANT OPTION。 CREATE ROUTINE不是例程级别的特权,因为您必须具有全局或数据库级别的特权才能首先创建例程。
MySQL 将例程级特权存储在mysql.procs_priv
系统 table 中。
代理用户权限
PROXY特权使一个用户可以成为另一个用户的代理。代理用户模拟或获取代理用户的身份;也就是说,它假定了代理用户的特权。
GRANT PROXY ON 'localuser'@'localhost' TO 'externaluser'@'somehost';
授予PROXY时,它必须是GRANT语句中命名的唯一特权,不能提供REQUIRE
子句,并且唯一允许的WITH
选项是WITH GRANT OPTION
。
代理要求代理用户通过插件进行身份验证,该插件在代理用户连接时将代理用户的名称返回到服务器,并且代理用户具有代理用户的PROXY
特权。有关详细信息和示例,请参见第 6.2.14 节“代理用户”。
MySQL 将代理特权存储在mysql.proxies_priv
系统 table 中。
隐式帐户创建
如果在GRANT语句中命名的帐户不存在,则采取的操作取决于NO_AUTO_CREATE_USER SQL 模式:
-
如果未启用NO_AUTO_CREATE_USER,则GRANT创建帐户。 除非您使用
IDENTIFIED BY
指定非空密码,否则这是非常不安全的。 -
如果启用了NO_AUTO_CREATE_USER,则GRANT失败并且不会创建帐户,除非您使用
IDENTIFIED BY
指定非空密码或使用IDENTIFIED WITH
命名身份验证插件。
如果该帐户已经存在,则禁止IDENTIFIED WITH
,因为它仅用于创建新帐户时使用。
其他帐户 Feature
除基于用户名和凭据的常规身份验证外,MySQL 还可以检查 X.509 证书属性。有关在 MySQL 上使用 SSL 的背景信息,请参见第 6.3 节“使用加密的连接”。
可选的REQUIRE
子句为 MySQL 帐户指定与 SSL 相关的选项。语法与CREATE USER语句相同。有关详细信息,请参见第 13.7.1.2 节“ CREATE USER 语句”。
Note
从 MySQL 5.7.6 开始,不再使用GRANT定义帐户 SSL 特性。而是使用CREATE USER或ALTER USER构建或更改 SSLFeature。 GRANT功能将在将来的 MySQL 版本中删除。
可选的WITH
子句用于以下目的:
-
使用户能够向其他用户授予特权
-
为用户指定资源限制
WITH GRANT OPTION
子句使用户能够将其在指定特权级别上拥有的任何特权授予其他用户。
要为帐户授予GRANT OPTION特权而又不更改其特权,请执行以下操作:
GRANT USAGE ON *.* TO 'someuser'@'somehost' WITH GRANT OPTION;
请向谁授予GRANT OPTION特权,因为具有不同特权的两个用户可能可以组合特权!
您不能授予其他用户您自己没有的特权; GRANT OPTION特权使您只能分配自己拥有的那些特权。
请注意,当您向用户授予特定特权级别的GRANT OPTION特权时,该用户在该级别拥有(或将来可能会授予)的任何特权也可以由该用户授予其他用户。假设您向用户授予数据库的INSERT特权。如果然后在数据库上授予SELECT特权并指定WITH GRANT OPTION
,则该用户不仅可以将SELECT特权也可以授予INSERT其他用户。然后,如果您向数据库中的用户授予UPDATE特权,则用户可以授予INSERT,SELECT和UPDATE。
对于非 Management 用户,不应全局授予ALTER特权,也不应授予mysql
系统数据库的特权。如果这样做,用户可以尝试通过重命名 table 来破坏特权系统!
有关与特定特权相关的安全风险的其他信息,请参阅第 6.2.2 节“ MySQL 提供的特权”。
如第 6.2.16 节“设置帐户资源限制”中所述,可以限制帐户对服务器资源的使用。为此,请使用WITH
子句指定一个或多个* resource_option
*值。未指定的限制将保留其当前值。语法与CREATE USER语句相同。有关详细信息,请参见第 13.7.1.2 节“ CREATE USER 语句”。
Note
从 MySQL 5.7.6 开始,不再使用GRANT来定义帐户资源限制。而是使用CREATE USER或ALTER USER构建或更改资源限制。 GRANT功能将在将来的 MySQL 版本中删除。
GRANT 的 MySQL 和标准 SQL 版本
MySQL 和标准 SQL 版本的GRANT之间的最大区别是:
-
MySQL 将特权与主机名和用户名的组合相关联,而不仅仅是用户名。
-
标准 SQL 没有全局或数据库级特权,也不支持 MySQL 支持的所有特权类型。
-
MySQL 不支持标准的 SQL
UNDER
特权。 -
标准 SQL 特权以分层的方式构造。如果删除用户,则将撤消已授予该用户的所有特权。如果您使用DROP USER,则在 MySQL 中也是如此。参见第 13.7.1.3 节“ DROP USER 语句”。
-
在标准 SQL 中,当您删除 table 时,该 table 的所有特权都将被吊销。在标准 SQL 中,当您撤消特权时,基于该特权授予的所有特权也会被撤消。在 MySQL 中,可以使用DROP USER或REVOKE语句删除特权。
-
在 MySQL 中,可能仅对 table 中的某些列具有INSERT特权。在这种情况下,只要仅为具有INSERT特权的列插入值,您仍可以在 table 上执行INSERT语句。如果未启用严格的 SQL 模式,则省略的列将设置为其隐式默认值。在严格模式下,如果任何省略的列都没有默认值,则该语句将被拒绝。 (标准 SQL 要求您在所有列上都具有INSERT特权。)有关严格 SQL 模式和隐式默认值的信息,请参见第 5.1.10 节“服务器 SQL 模式”和第 11.6 节“数据类型默认值”。