如果 partial_revokes
系统变量已启用,则可以授予全局生效的权限。具体来说,对于在全局级别拥有权限的用户,partial_revokes
使得可以撤销对特定模式的权限,同时保留对其他模式的权限。这样施加的权限限制可能对管理具有全局权限但应禁止访问某些模式的帐户很有用。例如,可以允许帐户修改除 mysql
系统模式中的表之外的任何表。
为了简洁起见,此处显示的 CREATE USER
语句不包含密码。在生产环境中,始终分配帐户密码。
partial_revokes
系统变量控制是否可以对帐户施加权限限制。默认情况下,partial_revokes
已禁用,尝试部分撤销全局权限会产生错误
mysql> CREATE USER u1;
mysql> GRANT SELECT, INSERT ON *.* TO u1;
mysql> REVOKE INSERT ON world.* FROM u1;
ERROR 1141 (42000): There is no such grant defined for user 'u1' on host '%'
要允许 REVOKE
操作,请启用 partial_revokes
SET PERSIST partial_revokes = ON;
SET PERSIST
设置运行的 MySQL 实例的值。它还保存该值,使其在随后的服务器重新启动时保留。要更改运行的 MySQL 实例的值,而不将其保留在随后的服务器重新启动时,请使用 GLOBAL
关键字,而不是 PERSIST
。请参阅 第 15.7.6.1 节,“SET 语法用于变量赋值”。
启用 partial_revokes
后,部分撤销操作将成功
mysql> REVOKE INSERT ON world.* FROM u1;
mysql> SHOW GRANTS FOR u1;
+------------------------------------------+
| Grants for u1@% |
+------------------------------------------+
| GRANT SELECT, INSERT ON *.* TO `u1`@`%` |
| REVOKE INSERT ON `world`.* FROM `u1`@`%` |
+------------------------------------------+
SHOW GRANTS
在其输出中将部分撤销列为 REVOKE
语句。结果表明 u1
具有全局 SELECT
和 INSERT
权限,但不能对 world
模式中的表执行 INSERT
操作。也就是说,u1
对 world
表的访问是只读的。
服务器在 mysql.user
系统表中记录通过部分撤销实现的权限限制。如果帐户具有部分撤销,则其 User_attributes
列值将具有 Restrictions
属性
mysql> SELECT User, Host, User_attributes->>'$.Restrictions'
FROM mysql.user WHERE User_attributes->>'$.Restrictions' <> '';
+------+------+------------------------------------------------------+
| User | Host | User_attributes->>'$.Restrictions' |
+------+------+------------------------------------------------------+
| u1 | % | [{"Database": "world", "Privileges": ["INSERT"]}] |
+------+------+------------------------------------------------------+
尽管可以对任何模式施加部分撤销,但对 mysql
系统模式的权限限制尤其有用,因为它是防止常规帐户修改系统帐户的策略的一部分。请参阅 保护系统帐户免受常规帐户的操纵。
部分撤销操作受以下条件限制
可以使用部分撤销对不存在的模式施加限制,但前提是撤销的权限是在全局范围内授予的。如果权限未在全局范围内授予,则撤销对不存在的模式的权限会产生错误。
部分撤销仅在模式级别生效。不能对仅在全局范围内生效的权限(例如
FILE
或BINLOG_ADMIN
)或对表、列或例程权限使用部分撤销。在权限分配中,启用
partial_revokes
会导致 MySQL 将模式名称中未转义的_
和%
SQL 通配符字符解释为字面字符,就像它们被转义为\_
和\%
一样。由于这会改变 MySQL 解释权限的方式,因此建议在可能启用partial_revokes
的安装中避免在权限分配中使用未转义的通配符字符。
如前所述,模式级别权限的部分撤销在 SHOW GRANTS
输出中显示为 REVOKE
语句。这与 SHOW GRANTS
表示 “普通” 模式级别权限的方式不同。
授予模式级别权限后,会在输出中以其自身的
GRANT
语句表示。mysql> CREATE USER u1; mysql> GRANT UPDATE ON mysql.* TO u1; mysql> GRANT DELETE ON world.* TO u1; mysql> SHOW GRANTS FOR u1; +---------------------------------------+ | Grants for u1@% | +---------------------------------------+ | GRANT USAGE ON *.* TO `u1`@`%` | | GRANT UPDATE ON `mysql`.* TO `u1`@`%` | | GRANT DELETE ON `world`.* TO `u1`@`%` | +---------------------------------------+
撤销模式级别权限后,它们会从输出中消失。它们不会以
REVOKE
语句的形式出现。mysql> REVOKE UPDATE ON mysql.* FROM u1; mysql> REVOKE DELETE ON world.* FROM u1; mysql> SHOW GRANTS FOR u1; +--------------------------------+ | Grants for u1@% | +--------------------------------+ | GRANT USAGE ON *.* TO `u1`@`%` | +--------------------------------+
当用户授予权限时,授予者对权限的任何限制都会被受授者继承,除非受授者已经拥有不受限制的权限。考虑以下两个用户,其中一个用户拥有全局 SELECT
权限。
CREATE USER u1, u2;
GRANT SELECT ON *.* TO u2;
假设一个管理用户 admin
拥有全局但部分撤销的 SELECT
权限。
mysql> CREATE USER admin;
mysql> GRANT SELECT ON *.* TO admin WITH GRANT OPTION;
mysql> REVOKE SELECT ON mysql.* FROM admin;
mysql> SHOW GRANTS FOR admin;
+------------------------------------------------------+
| Grants for admin@% |
+------------------------------------------------------+
| GRANT SELECT ON *.* TO `admin`@`%` WITH GRANT OPTION |
| REVOKE SELECT ON `mysql`.* FROM `admin`@`%` |
+------------------------------------------------------+
如果 admin
全局授予 u1
和 u2
SELECT
权限,结果对于每个用户都不同。
如果
admin
全局授予u1
SELECT
权限,而u1
之前没有SELECT
权限,u1
将继承admin
的权限限制。mysql> GRANT SELECT ON *.* TO u1; mysql> SHOW GRANTS FOR u1; +------------------------------------------+ | Grants for u1@% | +------------------------------------------+ | GRANT SELECT ON *.* TO `u1`@`%` | | REVOKE SELECT ON `mysql`.* FROM `u1`@`%` | +------------------------------------------+
另一方面,
u2
已经拥有全局SELECT
权限,不受限制。GRANT
只能增加受授者现有的权限,而不能减少它们,因此,如果admin
全局授予u2
SELECT
权限,u2
不会继承admin
的限制。mysql> GRANT SELECT ON *.* TO u2; mysql> SHOW GRANTS FOR u2; +---------------------------------+ | Grants for u2@% | +---------------------------------+ | GRANT SELECT ON *.* TO `u2`@`%` | +---------------------------------+
如果 GRANT
语句包含 AS
子句,则应用的权限限制是子句指定的用户名/角色组合上的限制,而不是执行语句的用户上的限制。有关 user
AS
子句的信息,请参见 第 15.7.1.6 节,“GRANT 语句”。
授予帐户的新权限上的限制会添加到该帐户的任何现有限制中。
mysql> CREATE USER u1;
mysql> GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO u1;
mysql> REVOKE INSERT ON mysql.* FROM u1;
mysql> SHOW GRANTS FOR u1;
+---------------------------------------------------------+
| Grants for u1@% |
+---------------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO `u1`@`%` |
| REVOKE INSERT ON `mysql`.* FROM `u1`@`%` |
+---------------------------------------------------------+
mysql> REVOKE DELETE, UPDATE ON db2.* FROM u1;
mysql> SHOW GRANTS FOR u1;
+---------------------------------------------------------+
| Grants for u1@% |
+---------------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO `u1`@`%` |
| REVOKE UPDATE, DELETE ON `db2`.* FROM `u1`@`%` |
| REVOKE INSERT ON `mysql`.* FROM `u1`@`%` |
+---------------------------------------------------------+
权限限制的聚合适用于显式部分撤销权限(如刚刚所示)以及从执行语句的用户或 AS
子句中提到的用户隐式继承限制。user
如果帐户对某个模式有权限限制,
该帐户不能向其他帐户授予对受限模式或其中任何对象的权限。
另一个没有限制的帐户可以向受限帐户授予对受限模式或其中对象的权限。假设一个不受限制的用户执行以下语句
CREATE USER u1; GRANT SELECT, INSERT, UPDATE ON *.* TO u1; REVOKE SELECT, INSERT, UPDATE ON mysql.* FROM u1; GRANT SELECT ON mysql.user TO u1; -- grant table privilege GRANT SELECT(Host,User) ON mysql.db TO u1; -- grant column privileges
结果帐户拥有这些权限,并能够在受限模式内执行有限的操作。
mysql> SHOW GRANTS FOR u1; +-----------------------------------------------------------+ | Grants for u1@% | +-----------------------------------------------------------+ | GRANT SELECT, INSERT, UPDATE ON *.* TO `u1`@`%` | | REVOKE SELECT, INSERT, UPDATE ON `mysql`.* FROM `u1`@`%` | | GRANT SELECT (`Host`, `User`) ON `mysql`.`db` TO `u1`@`%` | | GRANT SELECT ON `mysql`.`user` TO `u1`@`%` | +-----------------------------------------------------------+
如果帐户对全局权限有限制,则可以通过以下任何操作消除限制。
由没有权限限制的帐户全局授予该帐户权限。
在模式级别授予权限。
全局撤销权限。
考虑一个用户 u1
,它全局拥有多个权限,但对 INSERT
、UPDATE
和 DELETE
有限制。
mysql> CREATE USER u1;
mysql> GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO u1;
mysql> REVOKE INSERT, UPDATE, DELETE ON mysql.* FROM u1;
mysql> SHOW GRANTS FOR u1;
+----------------------------------------------------------+
| Grants for u1@% |
+----------------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO `u1`@`%` |
| REVOKE INSERT, UPDATE, DELETE ON `mysql`.* FROM `u1`@`%` |
+----------------------------------------------------------+
从没有限制的帐户全局授予 u1
权限会消除权限限制。例如,要消除 INSERT
限制
mysql> GRANT INSERT ON *.* TO u1;
mysql> SHOW GRANTS FOR u1;
+---------------------------------------------------------+
| Grants for u1@% |
+---------------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO `u1`@`%` |
| REVOKE UPDATE, DELETE ON `mysql`.* FROM `u1`@`%` |
+---------------------------------------------------------+
在模式级别授予 u1
权限会消除权限限制。例如,要消除 UPDATE
限制
mysql> GRANT UPDATE ON mysql.* TO u1;
mysql> SHOW GRANTS FOR u1;
+---------------------------------------------------------+
| Grants for u1@% |
+---------------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO `u1`@`%` |
| REVOKE DELETE ON `mysql`.* FROM `u1`@`%` |
+---------------------------------------------------------+
撤销全局权限会消除权限,包括对它的任何限制。例如,要消除 DELETE
限制(以消除所有 DELETE
访问权限为代价)
mysql> REVOKE DELETE ON *.* FROM u1;
mysql> SHOW GRANTS FOR u1;
+-------------------------------------------------+
| Grants for u1@% |
+-------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE ON *.* TO `u1`@`%` |
+-------------------------------------------------+
如果帐户在全局级别和模式级别都拥有权限,则必须在模式级别撤销两次才能生效部分撤销。假设 u1
拥有这些权限,其中 INSERT
在全局级别和 world
模式上都有。
mysql> CREATE USER u1;
mysql> GRANT SELECT, INSERT ON *.* TO u1;
mysql> GRANT INSERT ON world.* TO u1;
mysql> SHOW GRANTS FOR u1;
+-----------------------------------------+
| Grants for u1@% |
+-----------------------------------------+
| GRANT SELECT, INSERT ON *.* TO `u1`@`%` |
| GRANT INSERT ON `world`.* TO `u1`@`%` |
+-----------------------------------------+
撤销 world
上的 INSERT
权限会撤销模式级别权限(SHOW GRANTS
不再显示模式级别的 GRANT
语句)。
mysql> REVOKE INSERT ON world.* FROM u1;
mysql> SHOW GRANTS FOR u1;
+-----------------------------------------+
| Grants for u1@% |
+-----------------------------------------+
| GRANT SELECT, INSERT ON *.* TO `u1`@`%` |
+-----------------------------------------+
再次撤销 world
上的 INSERT
权限会部分撤销全局权限(SHOW GRANTS
现在包含一个模式级别的 REVOKE
语句)。
mysql> REVOKE INSERT ON world.* FROM u1;
mysql> SHOW GRANTS FOR u1;
+------------------------------------------+
| Grants for u1@% |
+------------------------------------------+
| GRANT SELECT, INSERT ON *.* TO `u1`@`%` |
| REVOKE INSERT ON `world`.* FROM `u1`@`%` |
+------------------------------------------+
要为某些模式提供帐户访问权限,而不对其他模式提供访问权限,部分撤销提供了一种替代方法,可以替代显式授予模式级别访问权限而不授予全局权限的方法。这两种方法各有优缺点。
授予模式级别权限而不授予全局权限
添加新模式:默认情况下,现有帐户无法访问该模式。对于任何应该可以访问该模式的帐户,DBA 必须授予模式级别访问权限。
添加新帐户:DBA 必须为该帐户应该拥有访问权限的每个模式授予模式级别访问权限。
结合使用全局权限和部分撤销
添加新模式:具有全局权限的现有帐户可以访问该模式。对于任何不应该可以访问该模式的帐户,DBA 必须添加部分撤销。
添加新帐户:DBA 必须授予全局权限,以及对每个受限模式的部分撤销。
对于访问权限仅限于几个模式的帐户,使用显式模式级别授予方法更方便。对于对除几个模式以外的所有模式都有广泛访问权限的帐户,使用部分撤销方法更方便。
启用 partial_revokes
后,如果任何帐户有权限限制,则无法禁用它。如果存在任何此类帐户,禁用 partial_revokes
会失败。
对于尝试在启动时禁用
partial_revokes
,服务器会记录错误消息并启用partial_revokes
。对于尝试在运行时禁用
partial_revokes
,会发生错误,并且partial_revokes
值保持不变。
如果存在限制,要禁用 partial_revokes
,首先必须消除限制。
确定哪些帐户有部分撤销。
SELECT User, Host, User_attributes->>'$.Restrictions' FROM mysql.user WHERE User_attributes->>'$.Restrictions' <> '';
对于每个此类帐户,消除其权限限制。假设上一步显示帐户
u1
具有以下限制。[{"Database": "world", "Privileges": ["INSERT", "DELETE"]
消除限制可以使用多种方法完成。
全局授予权限,不带限制。
GRANT INSERT, DELETE ON *.* TO u1;
在模式级别授予权限。
GRANT INSERT, DELETE ON world.* TO u1;
全局撤销权限(假设不再需要它们)。
REVOKE INSERT, DELETE ON *.* FROM u1;
删除帐户本身(假设不再需要它)。
DROP USER u1;
消除所有权限限制后,就可以禁用部分撤销。
SET PERSIST partial_revokes = OFF;
在复制场景中,如果在任何主机上启用了 partial_revokes
,则必须在所有主机上启用它。否则,用于部分撤销全局权限的 REVOKE
语句对所有发生复制的主机不会产生相同的效果,这可能会导致复制不一致或错误。
当启用 partial_revokes
时,会以扩展语法记录到二进制日志中,用于 GRANT
语句,包括发出语句的当前用户及其当前活动角色。如果以这种方式记录的用户或角色在副本上不存在,则复制应用器线程会在 GRANT
语句处停止,并出现错误。确保在复制源服务器上发出或可能发出 GRANT
语句的所有用户帐户也存在于副本上,并且具有与源服务器上相同的角色集。