文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
Man Pages (TGZ) - 258.2Kb
Man Pages (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 參考手冊  /  ...  /  使用部分撤銷限制權限

8.2.12 使用部分撤銷限制權限

如果啟用了 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 具有全域 SELECTINSERT 權限,但 INSERT 無法在 world 結構描述中的表格上執行。也就是說,u1world 表格的存取權是唯讀的。

伺服器會在 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 系統結構描述的權限限制特別有用,因為它是防止一般帳戶修改系統帳戶策略的一部分。請參閱 保護系統帳戶,避免遭到一般帳戶操縱

部分撤銷操作受限於以下條件

  • 可以使用部分撤銷對不存在的結構描述設定限制,但前提是撤銷的權限是全域授與的。如果權限不是全域授與的,則針對不存在的結構描述撤銷該權限會產生錯誤。

  • 部分撤銷僅適用於綱要層級。您不能對僅全域適用的權限使用部分撤銷(例如 FILEBINLOG_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 權限授與 u1u2,則每個使用者的結果都不同。

  • 如果 admin 將全域 SELECT 權限授與一開始沒有 SELECT 權限的 u1,則 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 子句,則套用的權限限制是該子句指定的 user/role 組合的限制,而不是執行陳述式的使用者的限制。有關 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,該使用者擁有數個全域權限,但對 INSERTUPDATEDELETE 有限制。

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,必須先移除限制。

  1. 判斷哪些帳戶具有部分撤銷。

    SELECT User, Host, User_attributes->>'$.Restrictions'
    FROM mysql.user WHERE User_attributes->>'$.Restrictions' <> '';
  2. 對於每個此類帳戶,請移除其權限限制。假設上一步顯示帳戶 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 陳述式的所有使用者帳戶也存在於複本上,並且具有與來源上相同的角色集。