文档首页
MySQL 8.4 参考手册
8.4 中文镜像

MySQL 8.4 参考手册 · 中文镜像

正文为中文,英文原文默认隐藏。点击任意中文段落即可展开 / 收起对应英文原文。

打开官方英文原文 ↗

译文由机器翻译生成,仅供理解参考;有疑问请以官方英文原文为准。

MySQL 8.4 参考手册 / 8 安全 / 8.2 访问控制和账户管理 / 8.2.12 使用部分撤销的权限限制
中文点击中文段落可显示 / 隐藏英文原文本页译文覆盖 100%

8.2.12 使用部分撤销进行权限限制8.2.12 Privilege Restriction Using Partial Revokes

如果启用了partial_revokes 系统变量,就可以授予全局适用的权限。具体来说,对于拥有全局级别权限的用户,partial_revokes 允许撤销特定模式的权限,同时保留其他模式的权限。因此施加的权限限制对于管理拥有全局权限但不应被允许访问某些模式的帐户可能非常有用。例如,可以允许一个帐户修改任何表,但不包括 mysql 系统模式中的表。It is possible to grant privileges that apply globally if the partial_revokes system variable is enabled. Specifically, for users who have privileges at the global level, partial_revokes enables privileges for specific schemas to be revoked while leaving the privileges in place for other schemas. Privilege restrictions thus imposed may be useful for administration of accounts that have global privileges but should not be permitted to access certain schemas. For example, it is possible to permit an account to modify any table except those in the mysql system schema.

Note

为了简洁起见,这里显示的 CREATE USER 语句未包含密码。在生产环境中,请始终为账户分配密码。For brevity, CREATE USER statements shown here do not include passwords. For production use, always assign account passwords.

使用部分撤销Using Partial Revokes

partial_revokes 系统变量控制是否可以对帐户设置权限限制。默认情况下,partial_revokes 是禁用的,尝试部分撤销全局权限会产生错误:The partial_revokes system variable controls whether privilege restrictions can be placed on accounts. By default, partial_revokes is disabled and attempts to partially revoke global privileges produce an error:

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:To permit the REVOKE operation, enable partial_revokes:

SET PERSIST partial_revokes = ON;

SET PERSIST 为正在运行的 MySQL 实例设置一个值。它还会保存该值,使其在随后的服务器重启中保留。要更改正在运行的 MySQL 实例的值而不让其在随后的重启中保留,请使用 GLOBAL 关键字而不是 PERSIST。参见 第 15.7.6.1 节,“SET 变量赋值语法”。SET PERSIST sets a value for the running MySQL instance. It also saves the value, causing it to carry over to subsequent server restarts. To change the value for the running MySQL instance without having it carry over to subsequent restarts, use the GLOBAL keyword rather than PERSIST. See Section 15.7.6.1, “SET Syntax for Variable Assignment”.

启用 partial_revokes 后,部分撤销将成功:With partial_revokes enabled, the partial revoke succeeds:

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 权限,但 INSERT 无法在 world 模式的表上使用。也就是说,u1 对 world 表的访问仅限于读取。SHOW GRANTS lists partial revokes as REVOKE statements in its output. The result indicates that u1 has global SELECT and INSERT privileges, except that INSERT cannot be exercised for tables in the world schema. That is, access by u1 to world tables is read only.

服务器通过在 mysql.user 系统表中实施部分撤销来记录权限限制。如果一个账户有部分撤销,其 User_attributes 列的值会有一个 Restrictions 属性:The server records privilege restrictions implemented through partial revokes in the mysql.user system table. If an account has partial revokes, its User_attributes column value has a Restrictions attribute:

mysql> SELECT User, Host, User_attributes->>'$.Restrictions'
       FROM mysql.user WHERE User_attributes->>'$.Restrictions' <> '';
+------+------+------------------------------------------------------+
| User | Host | User_attributes->>'$.Restrictions'                   |
+------+------+------------------------------------------------------+
| u1   | %    | [{"Database": "world", "Privileges": ["INSERT"]}] |
+------+------+------------------------------------------------------+
Note

虽然可以对任何模式施加部分撤销,但特别是在 mysql 系统模式上实施的权限限制在防止普通账户修改系统账户的策略中非常有用。请参见 防止普通账户操作系统账户。Although partial revokes can be imposed for any schema, privilege restrictions on the mysql system schema in particular are useful as part of a strategy for preventing regular accounts from modifying system accounts. See Protecting System Accounts Against Manipulation by Regular Accounts.

部分撤销操作受以下条件约束:Partial revoke operations are subject to these conditions:

  • 可以使用部分撤销对不存在的模式施加限制,但前提是被撤销的权限是全局授予的。如果权限不是全局授予的,则对不存在的模式撤销该权限会产生错误。It is possible to use partial revokes to place restrictions on nonexistent schemas, but only if the revoked privilege is granted globally. If a privilege is not granted globally, revoking it for a nonexistent schema produces an error.

  • 部分撤销仅适用于模式级别。对于仅全局适用的权限(例如 FILE 或 BINLOG_ADMIN),或者表、列或例程权限,不能使用部分撤销。Partial revokes apply at the schema level only. You cannot use partial revokes for privileges that apply only globally (such as FILE or BINLOG_ADMIN), or for table, column, or routine privileges.

  • 在权限分配中,启用 partial_revokes 会导致 MySQL 将模式名称中未转义的 _ 和 % SQL 通配符字符解释为字面字符,就像它们已经被转义为 \_ 和 \% 一样。由于这会改变 MySQL 对权限的解释,因此在可能启用 partial_revokes 的安装环境中,建议在权限分配中避免使用未转义的通配符字符。In privilege assignments, enabling partial_revokes causes MySQL to interpret occurrences of unescaped _ and % SQL wildcard characters in schema names as literal characters, just as if they had been escaped as \_ and \%. Because this changes how MySQL interprets privileges, it may be advisable to avoid unescaped wildcard characters in privilege assignments for installations where partial_revokes may be enabled.

如前所述,模式级权限的部分撤销会在 SHOW GRANTS 输出中显示为 REVOKE 语句。这与 SHOW GRANTS 表示“普通”模式级权限的方式有所不同:As mentioned previously, partial revokes of schema-level privileges appear in SHOW GRANTS output as REVOKE statements. This differs from how SHOW GRANTS represents “plain” schema-level privileges:

  • 当被授予时,模式级权限会在输出中由它们自身的 GRANT 语句表示:When granted, schema-level privileges are represented by their own GRANT statements in the output:

    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 语句的形式出现:When revoked, schema-level privileges simply disappear from the output. They do not appear as REVOKE statements:

    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 权限:When a user grants a privilege, any restriction the grantor has on the privilege is inherited by the grantee, unless the grantee already has the privilege without the restriction. Consider the following two users, one of whom has the global SELECT privilege:

CREATE USER u1, u2;
GRANT SELECT ON *.* TO u2;

假设一个管理用户 admin 拥有一个全局但部分被撤销的 SELECT 权限:Suppose that an administrative user admin has a global but partially revoked SELECT privilege:

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,每个用户的结果会有所不同:If admin grants SELECT globally to u1 and u2, the result differs for each user:

  • If admin授予SELECT globally to u1, who has no SELECT privilege to begin with, u1 inherits the admin privilege restriction:If admin grants SELECT globally to u1, who has no SELECT privilege to begin with, u1 inherits the admin privilege restriction:

    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`@`%` |
    +------------------------------------------+
    
  • On the other hand, u2 already holds a global SELECT privilege without restriction. GRANT can only add to a grantee's existing privileges, not reduce them, so if admin授予SELECT globally to u2, u2 does not inherit the admin restriction:On the other hand, u2 already holds a global SELECT privilege without restriction. GRANT can only add to a grantee's existing privileges, not reduce them, so if admin grants SELECT globally to u2, u2 does not inherit the admin restriction:

    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 语句”。If a GRANT statement includes an AS user clause, the privilege restrictions applied are those on the user/role combination specified by the clause, rather than those on the user who executes the statement. For information about the AS clause, see Section 15.7.1.6, “GRANT Statement”.

对账户授予的新权限的限制将被添加到该账户现有的限制中:Restrictions on new privileges granted to an account are added to any existing restrictions for that account:

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 子句中提到的用户隐式继承时。Aggregation of privilege restrictions applies both when privileges are partially revoked explicitly (as just shown) and when restrictions are inherited implicitly from the user who executes the statement or the user mentioned in an AS user clause.

如果一个账户在某个模式上有权限限制:If an account has a privilege restriction on a schema:

  • 该账户不能向其他账户授予该受限模式或其中任何对象的权限。The account cannot grant to other accounts a privilege on the restricted schema or any object within it.

  • 另一个没有限制的账户可以向受限账户授予受限模式或其中对象的权限。假设一个无限制用户执行这些语句:Another account that does not have the restriction can grant privileges to the restricted account for the restricted schema or objects within it. Suppose that an unrestricted user executes these statements:

    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
    

    结果账户拥有这些权限,并能够在受限模式内执行有限操作:The resulting account has these privileges, with the ability to perform limited operations within the restricted schema:

    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`@`%`                |
    +-----------------------------------------------------------+
    

如果一个账户在全局权限上有限制,下列任何操作都可以移除该限制:If an account has a restriction on a global privilege, the restriction is removed by any of these actions:

  • 由没有该权限限制的账户在全局范围内授予该权限。Granting the privilege globally to the account by an account that has no restriction on the privilege.

  • 在模式级别授予该权限。Granting the privilege at the schema level.

  • 在全局范围撤销该权限。Revoking the privilege globally.

考虑一个用户 u1,他在全局拥有多个权限,但在 INSERT、UPDATE 和 DELETE 上有一些限制:Consider a user u1 who holds several privileges globally, but with restrictions on INSERT, UPDATE and 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 限制:Granting a privilege globally to u1 from an account with no restriction removes the privilege restriction. For example, to remove the INSERT restriction:

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 限制:Granting a privilege at the schema level to u1 removes the privilege restriction. For example, to remove the UPDATE restriction:

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 访问权限):Revoking a global privilege removes the privilege, including any restrictions on it. For example, to remove the DELETE restriction (at the cost of removing all DELETE access):

mysql> REVOKE DELETE ON *.* FROM u1;
mysql> SHOW GRANTS FOR u1;
+-------------------------------------------------+
| Grants for u1@%                                 |
+-------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE ON *.* TO `u1`@`%` |
+-------------------------------------------------+

如果一个账户在全局和模式级别都有某个权限,你必须在模式级别撤销两次才能实现部分撤销。假设 u1 拥有这些权限,其中 INSERT 权限在全局和 world 模式下都有:If an account has a privilege at both the global and schema levels, you must revoke it at the schema level twice to effect a partial revoke. Suppose that u1 has these privileges, where INSERT is held both globally and on the world schema:

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`@`%`   |
+-----------------------------------------+

撤销 INSERT 在 world 上,会撤销模式级别的权限(SHOW GRANTS 不再显示模式级别的 GRANT 语句):Revoking INSERT on world revokes the schema-level privilege (SHOW GRANTS no longer displays the schema-level GRANT statement):

mysql> REVOKE INSERT ON world.* FROM u1;
mysql> SHOW GRANTS FOR u1;
+-----------------------------------------+
| Grants for u1@%                         |
+-----------------------------------------+
| GRANT SELECT, INSERT ON *.* TO `u1`@`%` |
+-----------------------------------------+

再次撤销 INSERT 在 world 上,会对全局权限执行部分撤销(SHOW GRANTS 现在包括一个模式级别的 REVOKE 语句):Revoking INSERT on world again performs a partial revoke of the global privilege (SHOW GRANTS now includes a schema-level REVOKE statement):

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`@`%` |
+------------------------------------------+

部分撤销与显式模式授权Partial Revokes Versus Explicit Schema Grants

为了为某些模式提供账户访问权限而不影响其他模式,部分撤销提供了一种替代方法,相比于显式授予模式级访问权限而不授予全局权限的方法。两种方法各有优缺点。To provide access to accounts for some schemas but not others, partial revokes provide an alternative to the approach of explicitly granting schema-level access without granting global privileges. The two approaches have different advantages and disadvantages.

授予模式级权限而不授予全局权限:Granting schema-level privileges and not global privileges:

  • 添加新模式:默认情况下,现有账户无法访问该模式。对于任何应当可以访问该模式的账户,DBA 必须授予模式级访问权限。Adding a new schema: The schema is inaccessible to existing accounts by default. For any account to which the schema should be accessible, the DBA must grant schema-level access.

  • 添加新账户:DBA 必须为每个账户应当访问的模式授予模式级访问权限。Adding a new account: The DBA must grant schema-level access for each schema to which the account should have access.

结合全局权限和部分撤销:Granting global privileges in conjunction with partial revokes:

  • 添加新模式:具有全局权限的现有账户可以访问该模式。对于任何应当无法访问该模式的此类账户,DBA 必须添加部分撤销。Adding a new schema: The schema is accessible to existing accounts that have global privileges. For any such account to which the schema should be inaccessible, the DBA must add a partial revoke.

  • 添加新账户:DBA 必须授予全局权限,并对每个受限模式部分撤销权限。Adding a new account: The DBA must grant the global privileges, plus a partial revoke on each restricted schema.

使用显式模式级授权的方法对于访问仅限于少数模式的账户更为方便。使用部分撤销权限的方法对于访问几乎所有模式但排除少数模式的账户更为方便。The approach that uses explicit schema-level grant is more convenient for accounts for which access is limited to a few schemas. The approach that uses partial revokes is more convenient for accounts with broad access to all schemas except a few.

禁用部分撤销Disabling Partial Revokes

一旦启用,partial_revokes 如果任何账户存在权限限制,则无法禁用。如果存在这样的账户,禁用 partial_revokes 将失败:Once enabled, partial_revokes cannot be disabled if any account has privilege restrictions. If any such account exists, disabling partial_revokes fails:

要在存在限制时禁用 partial_revokes,必须先移除这些限制:To disable partial_revokes when restrictions exist, the restrictions first must be removed:

  1. 确定哪些账户有部分撤销:Determine which accounts have partial revokes:

    SELECT User, Host, User_attributes->>'$.Restrictions'
    FROM mysql.user WHERE User_attributes->>'$.Restrictions' <> '';
    
  2. 对于每个这样的账户,移除其权限限制。假设上一步显示账户 u1 具有这些限制:For each such account, remove its privilege restrictions. Suppose that the previous step shows account u1 to have these restrictions:

    [{"Database": "world", "Privileges": ["INSERT", "DELETE"]
    

    限制移除可以通过多种方式进行:Restriction removal can be done various ways:

    • 全局授予权限,无任何限制:Grant the privileges globally, without restrictions:

      GRANT INSERT, DELETE ON *.* TO u1;
      
    • 在模式级别授予权限:Grant the privileges at the schema level:

      GRANT INSERT, DELETE ON world.* TO u1;
      
    • 全局撤销权限(假设它们不再需要):Revoke the privileges globally (assuming that they are no longer needed):

      REVOKE INSERT, DELETE ON *.* FROM u1;
      
    • 删除帐户本身(假设它不再需要):Remove the account itself (assuming that it is no longer needed):

      DROP USER u1;
      

在移除所有权限限制后,可以禁用部分撤销:After all privilege restrictions are removed, it is possible to disable partial revokes:

SET PERSIST partial_revokes = OFF;

部分撤销与复制Partial Revokes and Replication

在复制场景中,如果在任何主机上启用了partial_revokes,则必须在所有主机上启用。否则,用于部分撤销全局权限的REVOKE语句在所有进行复制的主机上不会产生相同的效果,可能导致复制不一致或错误。In replication scenarios, if partial_revokes is enabled on any host, it must be enabled on all hosts. Otherwise, REVOKE statements to partially revoke a global privilege do not have the same effect for all hosts on which replication occurs, potentially resulting in replication inconsistencies or errors.

当启用 partial_revokes 时,GRANT 语句的扩展语法会被记录在二进制日志中,包括发出该语句的当前用户及其当前活动角色。如果以这种方式记录的用户或角色在从服务器上不存在,复制应用线程将在该 GRANT 语句处停止并报错。请确保所有在复制源服务器上发出或可能发出 GRANT 语句的用户账户在从服务器上也存在,并且拥有与源服务器上相同的角色集合。When partial_revokes is enabled, an extended syntax is recorded in the binary log for GRANT statements, including the current user that issued the statement and their currently active roles. If a user or a role recorded in this way does not exist on the replica, the replication applier thread stops at the GRANT statement with an error. Ensure that all user accounts that issue or might issue GRANT statements on the replication source server also exist on the replica, and have the same set of roles as they have on the source.