15.7.1.6 授权语句
GRANT
priv_type [(column_list)]
[, priv_type [(column_list)]] ...
ON [object_type] priv_level
TO user_or_role [, user_or_role] ...
[WITH GRANT OPTION]
[AS user
[WITH ROLE
DEFAULT
| NONE
| ALL
| ALL EXCEPT role [, role ] ...
| role [, role ] ...
]
]
}
GRANT PROXY ON user_or_role
TO user_or_role [, user_or_role] ...
[WITH GRANT OPTION]
GRANT role [, role] ...
TO user_or_role [, user_or_role] ...
[WITH ADMIN OPTION]
object_type: {
TABLE
| FUNCTION
| PROCEDURE
}
priv_level: {
*
| *.*
| db_name.*
| db_name.tbl_name
| tbl_name
| db_name.routine_name
}
user_or_role: {
user (see Section 8.2.4, “Specifying Account Names”)
| role (see Section 8.2.5, “Specifying Role Names”)
}
授权语句GRANT
将权限和角色分配给MySQL用户账户和角色。有多个方面的授权语句,以下主题下描述:
语句GRANT
允许系统管理员授予权限和角色,可以授予用户帐户和角色。这些语法限制适用:
-
GRANT
不能在同一个语句中同时授予权限和角色。给定的GRANT
语句必须授予权限或角色。 -
ON子句区分语句是否授予权限或角色:
-
使用
ON
,语句授予权限。 -
不使用
ON
,语句授予角色。 -
可以将权限和角色同时分配给一个帐户,但必须使用单独的
GRANT
语句,每个语句都适用于要授予的内容。
-
关于角色的更多信息,请参见第8.2.10节,“使用角色”。
要使用GRANT
授予权限,您必须拥有GRANT OPTION
权限,并且您必须拥有要授予权限的权限。 (或者,如果您在mysql系统架构中的grant表中拥有UPDATE
权限,可以授予权限给任何账户任何权限。)当read_only
系统变量启用时,GRANT
还需要CONNECTION_ADMIN
权限(或弃用的SUPER
权限)。
GRANT
语句要么对所有命名用户和角色成功,要么回滚并无效,如果出现任何错误。该语句只有在所有命名用户和角色都成功时才会写入二进制日志。
REVOKE
语句与GRANT
相关,用于管理员删除账户权限。请参阅第15.7.1.8节,“REVOKE Statement”。
每个帐户名称都使用在第8.2.4节,“指定帐户名称”中描述的格式,每个角色名称都使用在第8.2.5节,“指定角色名称”中描述的格式。例如:
GRANT ALL ON db1.* TO 'jeffrey'@'localhost';
GRANT 'role1', 'role2' TO 'user1'@'localhost', 'user2'@'localhost';
GRANT SELECT ON world.* TO 'role3';
帐户或角色名称中的主机名部分,如果省略,默认为'%'
。
通常,数据库管理员首先使用CREATE USER
创建帐户并定义其非特权特征,如密码、是否使用安全连接和对服务器资源的访问限制,然后使用GRANT
定义其权限。ALTER USER
可以用来更改现有帐户的非特权特征。例如:
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;
从mysql程序中,GRANT
在执行成功时响应为Query OK, 0 rows affected
。要确定操作结果的权限,请使用SHOW GRANTS
。请参阅第15.7.7.22节,“SHOW GRANTS 语句”。
在某些情况下,GRANT
可能会被记录到服务器日志或客户端的历史文件中,如~/.mysql_history
,这意味着明文密码可能会被读取由该信息拥有读权限的人。关于服务器日志和控制的条件,以及如何控制,请见第8.1.2.3节,“密码和记录”。关于客户端日志的类似信息,请见第6.5.1.3节,“mysql 客户端记录”。
GRANT
支持最长255个字符的主机名。用户名可以是32个字符以下。数据库、表、列和存储程序名称可以是64个字符以下。
不要尝试通过修改mysql.user
系统表来更改可接受的用户名长度。这可能会导致不可预测的行为,甚至使用户无法登录到 MySQL 服务器。从不对mysql
系统架构中的表结构进行任何修改,除非按照第3章,《升级 MySQL》中描述的过程。
在GRANT
语句中,有些对象需要使用引号,虽然在许多情况下引号是可选的:Account、role、database、table、column 和 routine 名称。例如,如果一个user_name
或host_name
值在账户名称中是合法的未引号标识符,你不需要引号它。但是,引号是必要的,以指定包含特殊字符(例如-
)的user_name
字符串或包含特殊字符或通配符(例如%
)的host_name
字符串。单独引号用户名称和主机名称。
指定引用的值:
-
将数据库、表、列和 routine 名称作为标识符引用。
-
将用户名称和主机名称作为标识符或字符串引用。
-
将密码作为字符串引用。
关于字符串引用的指南和标识符引用的指南,请参阅第11.1.1节,“字符串字面量”,和第11.2节,“schema 对象名称”。
下面的几个段落中描述的通配符字符%
和_
的使用已经被弃用,因此在 MySQL 的未来版本中可能会被删除。
在GRANT
语句中,用于指定数据库名称的_
和%
通配符是允许的(例如:GRANT ... ON
)。这意味着,例如,要使用一个db_name
.*_
字符作为数据库名称的一部分,可以在GRANT
语句中使用\
转义字符将其指定为\_
,以防止用户访问匹配通配模式的额外数据库(例如:GRANT ... ON `foo\_bar`.* TO ...
)。
使用多个包含通配符的GRANT
语句可能不会对DML语句产生预期的效果;当MySQL解析涉及通配符的授权时,只会考虑第一个匹配的授权。在其他字样,如果用户拥有两个使用通配符的数据库级别授权,匹配同一数据库的授权,那么创建的最早的一项授权将被应用。考虑到数据库db
和表t
使用以下语句创建:
mysql> CREATE DATABASE db;
Query OK, 1 row affected (0.01 sec)
mysql> CREATE TABLE db.t (c INT);
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO db.t VALUES ROW(1);
Query OK, 1 row affected (0.00 sec)
下一步(假设当前账户是MySQL root
账户或另一个拥有必要权限的账户),我们创建用户u
然后发出两个包含通配符的GRANT
语句,如下所示:
mysql> CREATE USER u;
Query OK, 0 rows affected (0.01 sec)
mysql> GRANT SELECT ON `d_`.* TO u;
Query OK, 0 rows affected (0.01 sec)
mysql> GRANT INSERT ON `d%`.* TO u;
Query OK, 0 rows affected (0.00 sec)
mysql> EXIT
Bye
如果我们结束会话,然后使用mysql 客户端重新登录,作为u,我们看到这个账户只有第一个匹配的授权提供的权限,而不是第二个:
$> mysql -uu -hlocalhost
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.4.0-tr Source distribution
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input
statement.
mysql> TABLE db.t;
+------+
| c |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
mysql> INSERT INTO db.t VALUES ROW(2);
ERROR 1142 (42000): INSERT command denied to user 'u'@'localhost' for table 't'
在权限分配中,MySQL 将未转义的_
和%
SQL通配符字符在数据库名称中的出现解释为字面字符,在以下情况下发生:
-
当数据库名称不用于在数据库级别授予权限,但用作授予某些其他对象(例如表或存储程序)的 qualifier(例如
GRANT ... ON
)时。db_name
.tbl_name
-
启用
partial_revokes
将使 MySQL 将未转义的_
和%
通配符字符在数据库名称中的出现解释为字面字符,就像它们已经被转义为\_
和partial_revokes
的情况下。更多信息,请参见第8.2.12节,“使用部分撤销限制权限”。
在GRANT
语句中,user
值表示 MySQL 账户,该语句适用于该账户。为了支持将权限授予来自任意主机的用户,MySQL 支持在 user
值中指定形式为 '
。user_name
'@'host_name
'
您可以在主机名称中指定通配符。例如,'
将适用于 user_name
'@'%.example.com'user_name
对于 example.com 域中的任何主机,而 '
将适用于 user_name
'@'198.51.100.%'user_name
对于 198.51.100 类 C 子网中的任何主机。
简单形式 '
是对 user_name
''
的同义词。user_name
'@'%'
MySQL 自动将授予给 '
的所有权限授予给 username
'@'%''
账户。这一行为已弃用,并且将在 MySQL 未来版本中删除。username
'@'localhost'
MySQL 不支持用户名称中的通配符。要引用匿名用户,请使用GRANT
语句指定一个空用户名称:
GRANT ALL ON test.* TO ''@'localhost' ...;
在这种情况下,任何连接到本地主机并使用正确密码的匿名用户都被允许访问,具有与匿名用户账户关联的权限。
关于帐户名称中的用户名和主机名称值,请参见第8.2.4节,“指定帐户名称”。
如果您允许本地匿名用户连接到 MySQL 服务器,您也应该将所有本地用户授予'
的权限。否则,当命名用户尝试从本地机器登录到 MySQL 服务器时,MySQL 服务器将使用user_ name
'@'localhost'localhost
在mysql.user
系统表中的匿名用户账户。详细信息请见第8.2.6节,“连接验证,阶段 1:连接验证”。
要确定是否存在这个问题,请执行以下查询,该查询列出任何匿名用户:
SELECT Host, User FROM mysql.user WHERE User='';
要避免前面描述的问题,请使用以下语句删除本地匿名用户账户:
DROP USER ''@'localhost';
以下表格总结了可以在GRANT
和REVOKE
语句中指定的静态和动态priv_type
特权类型,以及每个特权可以在哪些级别上授予。关于每个特权的详细信息,请见第8.2.2节,“MySQL提供的特权”。关于静态和动态特权之间的差异,请见静态 versus 动态特权。
表15.11:GRANT和REVOKE语句中的可允许的静态特权
Privilege | Meaning and Grantable Levels |
---|---|
ALL [PRIVILEGES] |
在指定访问级别上授予所有特权,除GRANT OPTION 和PROXY 外。 |
ALTER |
启用ALTER TABLE 语句。级别:全局、数据库、表。 |
ALTER ROUTINE |
启用存储程序被更改或删除。级别:全局、数据库、程序。 |
CREATE |
启用数据库和表的创建。级别:全局、数据库、表。 |
CREATE ROLE |
启用角色的创建。级别:全局。 |
CREATE ROUTINE |
启用存储程序的创建。级别:全局、数据库。 |
CREATE TABLESPACE |
启用表空间和日志文件组的创建、修改或删除。级别:全局。 |
CREATE TEMPORARY TABLES |
启用使用CREATE TEMPORARY TABLE 。级别:全局、数据库。 |
CREATE USER |
启用使用CREATE USER 、DROP USER 、RENAME USER 和REVOKE ALL PRIVILEGES 。级别:全局。 |
CREATE VIEW |
启用视图的创建或更改。级别:全局、数据库、表。 |
DELETE |
启用DELETE 语句。级别:全局、数据库、表。 |
DROP |
启用删除数据库、表和视图的权限。级别:全局、数据库、表。 |
DROP ROLE |
启用删除角色的权限。级别:全局。 |
EVENT |
启用事件调度器的事件使用。级别:全局、数据库。 |
EXECUTE |
启用存储程序的执行权限。级别:全局、数据库、程序。 |
FILE |
启用服务器读取或写入文件的权限。级别:全局。 |
FLUSH_ |
启用FLUSH PRIVILEGES 语句。级别:全局。 |
GRANT OPTION |
启用授予或撤销其他账户的权限。级别:全局、数据库、表、程序、代理。 |
INDEX |
启用创建或删除索引。级别:全局、数据库、表。 |
INSERT |
启用使用INSERT 。级别:全局、数据库、表、列。 |
LOCK TABLES |
启用对您拥有SELECT 特权的表上使用LOCK TABLES 。级别:全局、数据库。 |
OPTIMIZE_LOCAL_TABLE |
启用使用OPTIMIZE LOCAL TABLE 或OPTIMIZE NO_WRITE_TO_BINLOG TABLE 。级别:全局、数据库、表。 |
PROCESS |
启用用户使用SHOW PROCESSLIST 查看所有进程。级别:全局。 |
PROXY |
启用用户代理。级别:从用户到用户。 |
REFERENCES |
启用外键创建。级别:全局、数据库、表、列。 |
RELOAD |
启用使用FLUSH 操作。级别:全局。 |
REPLICATION CLIENT |
启用用户询问源服务器或副本服务器的位置。级别:全局。 |
REPLICATION SLAVE |
启用副本从源服务器读取二进制日志事件。级别:全局。 |
SELECT |
启用使用SELECT 。级别:全局、数据库、表、列。 |
SHOW DATABASES |
启用SHOW DATABASES 显示所有数据库。级别:全局。 |
SHOW VIEW |
启用使用SHOW CREATE VIEW 。级别:全局、数据库、表。 |
SHUTDOWN |
启用使用mysqladmin shutdown。级别:全局。 |
SUPER |
启用其他管理操作,如CHANGE REPLICATION SOURCE TO 、KILL 、PURGE BINARY LOGS 、SET GLOBAL 和mysqladmin debug命令。级别:全局。 |
TRIGGER |
启用触发器操作。级别:全局、数据库、表。 |
UPDATE |
启用使用UPDATE 。级别:全局、数据库、表、列。 |
USAGE |
“无权限”同义词。 |
表15.12:GRANT和REVOKE的可允许动态权限
Privilege | Meaning and Grantable Levels |
---|---|
APPLICATION_PASSWORD_ADMIN |
启用双重密码管理。级别:全局。 |
AUDIT_ABORT_EXEMPT |
允许被审核日志过滤阻止的查询。级别:全局。 |
AUDIT_ADMIN |
启用审核日志配置。级别:全局。 |
AUTHENTICATION_POLICY_ADMIN |
启用身份验证策略管理。级别:全局。 |
BACKUP_ADMIN |
启用备份管理。级别:全局。 |
BINLOG_ADMIN |
启用二进制日志控制。级别:全局。 |
BINLOG_ENCRYPTION_ADMIN |
启用二进制日志加密激活和停用。级别:全局。 |
CLONE_ADMIN |
启用克隆管理。级别:全局。 |
CONNECTION_ADMIN |
启用连接限制/限制控制。级别:全局。 |
ENCRYPTION_KEY_ADMIN |
启用InnoDB密钥轮换。级别:全局。 |
FIREWALL_ADMIN |
启用防火墙规则管理,任何用户。级别:全局。 |
FIREWALL_EXEMPT |
免除用户防火墙限制。级别:全局。 |
FIREWALL_USER |
启用防火墙规则管理,自己。级别:全局。 |
FLUSH_OPTIMIZER_COSTS |
启用优化器成本重新加载。级别:全局。 |
FLUSH_STATUS |
启用状态指示符刷新。级别:全局。 |
FLUSH_TABLES |
启用表刷新。级别:全局。 |
FLUSH_USER_RESOURCES |
启用用户资源刷新。级别:全局。 |
GROUP_REPLICATION_ADMIN |
启用Group Replication控制。级别:全局。 |
INNODB_REDO_LOG_ARCHIVE |
启用 redo 日志归档管理。级别:全局。 |
INNODB_REDO_LOG_ENABLE |
启用或禁用 redo 记录。级别:全局。 |
NDB_STORED_USER |
启用 SQL 节点之间用户或角色共享(NDB 集群)。级别:全局。 |
PASSWORDLESS_USER_ADMIN |
启用无密码用户账户管理。级别:全局。 |
PERSIST_RO_VARIABLES_ADMIN |
启用持久化只读系统变量。级别:全局。 |
REPLICATION_APPLIER |
作为 PRIVILEGE_CHECKS_USER 对象进行复制通道操作。级别:全局。 |
REPLICATION_SLAVE_ADMIN |
启用定期复制控制。级别:全局。 |
RESOURCE_GROUP_ADMIN |
启用资源组管理。级别:全局。 |
RESOURCE_GROUP_USER |
启用资源组管理。级别:全局。 |
ROLE_ADMIN |
启用角色授予或撤销,使用WITH ADMIN OPTION 。级别:全局。 |
SESSION_VARIABLES_ADMIN |
启用设置受限会话系统变量。级别:全局。 |
SHOW_ROUTINE |
启用访问存储程序定义。级别:全局。 |
SKIP_QUERY_REWRITE |
不重写由该用户执行的查询。级别:全局。 |
SYSTEM_USER |
将账户设计为系统账户。级别:全局。 |
SYSTEM_VARIABLES_ADMIN |
启用修改或持久化全局系统变量。级别:全局。 |
TABLE_ENCRYPTION_ADMIN |
启用Override默认加密设置。级别:全局。 |
TELEMETRY_LOG_ADMIN |
启用MySQL HeatWave on AWS的telemetry日志配置。级别:全局。 |
TP_连接_admin |
启用线程池连接管理。级别:全局。 |
版本令牌_admin |
启用版本令牌函数使用。级别:全局。 |
XA_恢复_admin |
启用XA RECOVER 执行。级别:全局。 |
触发器与表相关联。要创建或删除触发器,您必须对该表拥有TRIGGER
特权,而不是触发器本身。
在GRANT
语句中,ALL [PRIVILEGES]
或PROXY
特权必须单独指定,而不能与其他特权一起指定。ALL [PRIVILEGES]
表示可供在特定级别上授予的所有特权,除了GRANT OPTION
和PROXY
特权。
MySQL 账户信息存储在 mysql
系统架构的表中。欲了解更多细节,请参阅第8.2节,“Access Control and Account Management”,该节详细讨论了 mysql
系统架构和访问控制系统。
如果授权表中包含混合大小写数据库或表名的特权行,并且lower_case_table_names
系统变量设置为非零值,则REVOKE
语句不能用来撤销这些特权。这种情况下需要直接操作授权表。(GRANT
语句在lower_case_table_names
设置时不会创建这些行,但是在设置该变量之前可能已经创建了这些行。该变量只能在服务器启动时配置。)
特权可以根据用于 ON
子句的语法不同,授予于多个级别上。对于REVOKE
语句,同样使用 ON
子句指定要删除的特权。
在全局、数据库、表和存储程序级别上,GRANT ALL
只分配存在于您正在授予的级别上的权限。例如,GRANT ALL ON
是一个数据库级语句,因此不授予任何全局唯一权限,如db_name
.*FILE
。授予权限ALL
不分配GRANT OPTION
或PROXY
权限。
如果存在,object_类型
子句应该指定为 TABLE
、FUNCTION
或 PROCEDURE
,当以下对象是一个表、存储函数或存储程序时。
用户在数据库、表、列或存储程序上持有的权限是各个权限级别的账户权限的逻辑OR
组合,包括全局级别。不能通过在较低级别中缺少该权限来否定在更高级别授予的权限。例如,这个语句授予了SELECT
和 INSERT
权限_globally:
GRANT SELECT, INSERT ON *.* TO u1;
授予的全局权限适用于所有数据库、表和列,即使在任何较低级别中没有授予。
可以通过启用partial_ revokes
系统变量来明确地否决全局级别授予的特定权限:
GRANT SELECT, INSERT, UPDATE ON *.* TO u1;
REVOKE INSERT, UPDATE ON db1.* FROM u1;
前面的语句结果是SELECT
在所有表中生效,而INSERT
和UPDATE
除在db1
中外生效。对db1
的账户访问是只读。
权限检查过程的详细信息见第8.2.7节,“Access Control, Stage 2: Request Verification”。
如果您对任何用户使用表、列或存储过程权限,服务器将检查所有用户的表、列和存储过程权限,这会使MySQL运行速度下降。类似地,如果您限制了任何用户的查询、更新或连接数,服务器必须监控这些值。
MySQL 允许您授予不存在的数据库或表的权限。对于表,需要授予CREATE
权限。这是设计行为,旨在使数据库管理员能够为将来创建的数据库或表准备用户账户和权限。
MySQL 不会自动撤销任何权限,当您删除数据库或表时。然而,如果您删除一个存储程序,那么为该存储程序授予的存储程序级别权限将被撤销。
全局权限是管理员权限或对某个服务器上的所有数据库的权限。要分配全局权限,请使用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 等静态权限是管理员权限,不能在更高级别上授予。
动态权限都是全局权限,不能在更高级别上授予。
其他权限可以在更高级别上授予或授予。
在全局级别授予GRANT OPTION
的效果对静态和动态权限不同:
-
GRANT OPTION
授予任何静态全局权限将应用于所有静态全局权限。 -
GRANT OPTION
授予任何动态权限仅适用于该动态权限。
GRANT ALL
在全局级别授予所有静态全局权限和当前已注册的动态权限。执行GRANT
语句后注册的动态权限将不会被自动授予任何账户。
MySQL 将全局权限存储在mysql.user
系统表中。
数据库权限适用于给定数据库中的所有对象。要分配数据库级别的权限,请使用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
权限。表或存储程序的权限也可以在数据库级别指定,以便对该数据库中的所有表或存储程序生效。
MySQL 将数据库权限存储在mysql.db
系统表中。
表权限适用于该表中的所有列。要分配表级权限,请使用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
。如果没有默认数据库,则出现错误。
表级别的priv_type
值包括:ALTER
,CREATE VIEW
,CREATE
,DELETE
,DROP
,GRANT OPTION
,INDEX
,INSERT
,REFERENCES
,SELECT
,SHOW VIEW
,TRIGGER
和UPDATE
。
表级别的权限适用于基本表和视图,不适用于使用CREATE TEMPORARY TABLE
创建的表,即使表名相同。关于TEMPORARY
表权限,请参阅第15.1.20.2节,“CREATE TEMPORARY TABLE Statement”。
MySQL 将表权限存储在 mysql.tables_priv
系统表中。
列权限适用于给定表中的单个列。要授予在列级别的每个权限,必须在括号中将该列或列列表跟随。
GRANT SELECT (col1), INSERT (col1, col2) ON mydb.mytbl TO 'someuser'@'somehost';
当使用 column_list
子句时,列 (即 column) 的可允许的 priv_type
值是INSERT
、REFERENCES
、SELECT
和UPDATE
。
MySQL 将列权限存储在 mysql.columns_priv
系统表中。
以下权限适用于存储程序(过程和函数):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
系统表中。
权限PROXY
允许一个用户充当另一个用户的代理,该代理用户模拟或取代被代理用户的身份,即假设被代理用户的权限。
GRANT PROXY ON 'localuser'@'localhost' TO 'externaluser'@'somehost';
PROXY
授予权限时,必须是GRANT
语句中唯一的权限,并且唯一允许的WITH
选项是WITH GRANT OPTION
。
代理需要代理用户通过返回被代理用户名称的插件来验证身份,并且代理用户必须对被代理用户拥有
PROXY
权限。详细信息和示例,请见第8.2.19节,“代理用户”。
MySQL 将代理权限存储在
mysql.proxies_priv
系统表中。
GRANT
语句没有ON
子句授予权限将授予角色,而不是单个权限。一个角色是命名的权限集合;见第8.2.10节,“使用角色”。例如:
GRANT 'role1', 'role2' TO 'user1'@'localhost', 'user2'@'localhost';
每个要授予的角色都必须存在,以及每个用户账户或角色到哪儿它是要授予的。角色不能授予匿名用户。
授予权限不自动激活角色。关于角色激活和停用信息,请见激活角色。
授予权限需要以下权限:
-
如果您拥有
ROLE_ADMIN
特权(或弃用的SUPER
特权),可以将任何角色授予用户或角色。 -
如果您使用包含
GRANT
语句的角色授予了一个角色,并且该语句包括WITH ADMIN OPTION
子句,您将能够在授予或撤销该角色时授予或撤销其他用户或角色,该角色必须在您授予或撤销时处于活动状态。这还包括使用WITH ADMIN OPTION
本身的能力。 -
要授予具有
SYSTEM_USER
特权的角色,您必须拥有SYSTEM_USER
特权。
使用GRANT
语句可以创建环形引用。例如:
CREATE USER 'u1', 'u2';
CREATE ROLE 'r1', 'r2';
GRANT 'u1' TO 'u1'; -- simple loop: u1 => u1
GRANT 'r1' TO 'r1'; -- simple loop: r1 => r1
GRANT 'r2' TO 'u2';
GRANT 'u2' TO 'r2'; -- mixed user/role loop: u2 => r2 => u2
环形授予引用是允许的,但不会向受益者添加新的特权或角色,因为用户或角色已经拥有其特权和角色。
GRANT
语句可以使用一个AS
子句来指定执行语句时的权限上下文信息。该语法在 SQL 层面可见,但其主要目的是使得部分撤销对 grantor 权限的限制在所有节点上均生效,从而在二进制日志中显示这些限制。关于部分撤销的信息,请参阅第8.2.12节,“使用部分撤销的权限限制”。user
[WITH ROLE]
当指定了AS
子句时,语句执行将考虑与命名用户相关的所有权限限制,包括如果存在的话的所有角色指定于user
WITH ROLE
中。结果是实际授予语句的权限可能相对减少。
以下条件适用于AS
子句:user
-
AS
只有在命名的user
拥有权限限制(这意味着<a class="link" href="server-system-variables.html#sysvar_partial_revokes"><code class="literal">partial_revokes</code></a> 系统变量启用)时才生效。 -
如果指定了
WITH ROLE
,那么所有命名的角色都必须授予给命名的user
。 -
指定的
用户
应该是一个 MySQL 账户,格式为'
、用户名
'@'host_name
'CURRENT_USER
或CURRENT_USER()
。执行用户可能与WITH ROLE
一起指定,以便在执行时使用一组不同的角色集,而不是当前会话中的角色集。 -
AS
不能用于获取执行GRANT
语句的用户不拥有的权限。执行用户至少需要授予的权限,但AS
子句只能限制授予的权限,而不是扩大它们。 -
在授予权限方面,
AS
不能指定一个用户/角色组合,该组合拥有执行GRANT
语句的用户拥有的更多权限(更少的限制)。执行用户可以拥有更多权限,但只能在语句中不授予这些额外权限时。 -
AS
仅支持授予全局权限(ON *.*
)。 -
AS
对PROXY
授权不支持。
以下示例演示了AS
子句的效果。创建一个用户u1
,该用户拥有某些全局权限,同时对这些权限施加限制:
CREATE USER u1;
GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO u1;
REVOKE INSERT, UPDATE ON schema1.* FROM u1;
REVOKE SELECT ON schema2.* FROM u1;
同时创建一个角色r1
,该角色部分地解除一些权限限制,并授予该角色给u1
:
CREATE ROLE r1;
GRANT INSERT ON schema1.* TO r1;
GRANT SELECT ON schema2.* TO r1;
GRANT r1 TO u1;
现在,使用没有任何权限限制的账户,授予多个用户相同的全局权限,但是每个用户都有不同的限制,由于AS
子句而施加,并检查实际授予的权限:
-
GRANT
语句这里没有AS
子句,所以授予的权限恰好是指定的:mysql> CREATE USER u2; mysql> GRANT SELECT, INSERT, UPDATE ON *.* TO u2; mysql> SHOW GRANTS FOR u2; +-------------------------------------------------+ | Grants for u2@% | +-------------------------------------------------+ | GRANT SELECT, INSERT, UPDATE ON *.* TO `u2`@`%` | +-------------------------------------------------+
-
GRANT
语句这里有AS
子句,所以授予的权限是指定的,但是来自u1
的限制也被应用:mysql> CREATE USER u3; mysql> GRANT SELECT, INSERT, UPDATE ON *.* TO u3 AS u1; mysql> SHOW GRANTS FOR u3; +----------------------------------------------------+ | Grants for u3@% | +----------------------------------------------------+ | GRANT SELECT, INSERT, UPDATE ON *.* TO `u3`@`%` | | REVOKE INSERT, UPDATE ON `schema1`.* FROM `u3`@`%` | | REVOKE SELECT ON `schema2`.* FROM `u3`@`%` | +----------------------------------------------------+
如前所述,
AS
子句只能添加权限限制,而不能escalate权限。因此,虽然u1
拥有DELETE
权限,但是由于语句没有指定授予DELETE
权限,所以不包括在授予的权限中。 -
在
GRANT
语句中,AS
子句使得角色r1
对于用户u1
成为活动的。该角色对u1
的一些限制被取消。因此,授予的权限有一些限制,但不是之前GRANT
语句那样多:mysql> CREATE USER u4; mysql> GRANT SELECT, INSERT, UPDATE ON *.* TO u4 AS u1 WITH ROLE r1; mysql> SHOW GRANTS FOR u4; +-------------------------------------------------+ | Grants for u4@% | +-------------------------------------------------+ | GRANT SELECT, INSERT, UPDATE ON *.* TO `u4`@`%` | | REVOKE UPDATE ON `schema1`.* FROM `u4`@`%` | +-------------------------------------------------+
如果GRANT
语句包含一个AS
子句,执行语句的用户对该语句的权限限制将被忽略(而不是像在没有user
AS
子句时那样应用):
可选的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
权限。
对于非管理员用户,不应该将ALTER
权限授予全局或mysql系统架构。如果你这样做,那么用户可以尝试篡改权限系统!
关于特定权限相关的安全风险,见第8.2.2节,“MySQL提供的权限”。
MySQL和标准SQL版本GRANT
的最大差异是:
-
MySQL将权限与主机名和用户名的组合相关,而不是只与用户名相关。
-
标准SQL没有全局或数据库级别的权限,也不支持MySQL支持的一些权限类型。
-
MySQL不支持标准SQL中的
UNDER
权限。 -
标准SQL权限结构化方式是层次式。如果你删除了用户,那么该用户拥有的所有权限都会被撤销。这也适用于在使用
DROP USER
时的MySQL。如果你想了解更多,请见第15.7.1.5节,“DROP USER Statement”。 -
在标准SQL中,当您删除一个表时,所有该表的权限将被撤销。在标准SQL中,当您撤销一个权限时,也会撤销基于该权限授予的所有权限。在MySQL中,可以使用
DROP USER
或REVOKE
语句来删除权限。 -
在MySQL中,可以对某些表的某些列授予
INSERT
权限。在这种情况下,您仍然可以执行INSERT
语句,该表,只要您插入的值只包含那些您有INSERT
权限的列。省略的列将在非严格SQL模式下设置为隐式默认值。在严格模式下,如果省略的列没有默认值,该语句将被拒绝。 (标准SQL要求您对所有列拥有INSERT
权限。)有关严格SQL模式和隐式默认值的信息,请参见第7.1.11节,“服务器SQL模式”和第13.6节,“数据类型默认值”。