如果 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
全局地授予 SELECT
权限给 u1
和 u2
,每个用户的结果都不同。
如果
admin
全局地授予SELECT
权限给u1
,而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
全局地授予SELECT
权限给u2
,则u2
不会继承admin
限制。mysql> GRANT SELECT ON *.* TO u2; mysql> SHOW GRANTS FOR u2; +---------------------------------+ | Grants for u2@% | +---------------------------------+ | GRANT SELECT ON *.* TO `u2`@`%` | +---------------------------------+
如果 GRANT
语句包含 AS
子句,则应用的权限限制是该子句指定的 user/role 组合的限制,而不是执行该语句的用户所拥有的限制。有关 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
语句的所有用户帐户也存在于副本上,并且拥有与源服务器上相同的 роли 集合。