簡介
訪問控制和使用者管理是兩個隨著系統中使用者數量和不同資料庫實體增加而迅速變得複雜的領域。管理各種資料庫物件上的許多不同許可權,確保具有相同職責的使用者擁有相同的訪問級別,以及審計和縮小訪問範圍,所有這些都會隨著時間的推移變得更加困難。
為了解決這個問題,MySQL 有一個名為“角色”的概念,它允許您將許可權捆綁到給定的名稱下,從而能夠批次分配和修改設定。在本指南中,我們將介紹角色在 MySQL 中如何工作,以及如何使用它們來更輕鬆地管理使用者的資料訪問。
命令
以下是我們將在管理 MySQL 角色時討論的主要 SQL 命令。
CREATE ROLE:CREATE ROLE命令在資料庫系統中定義一個新角色。DROP ROLE:DROP ROLE命令執行相反的操作,刪除現有角色。GRANT:GRANT命令有兩個與角色相關的不同目的:向角色新增許可權,以及將使用者賬戶新增為角色的成員。REVOKE:在角色上下文中,REVOKE命令從角色中刪除許可權,並從使用者賬戶中刪除角色成員身份。SHOW GRANTS:SHOW GRANTS命令顯示給定使用者賬戶或角色的許可權。SET ROLE:SET ROLE命令更改使用者賬戶正在主動使用的角色。這允許您指定哪些許可權集適用於該會話的賬戶。SET DEFAULT ROLE:SET DEFAULT ROLE命令定義了當客戶端以特定使用者賬戶登入時自動應用的那些角色。
所需許可權
要跟著本指南操作,您需要以下許可權:
CREATE ROLEGRANT OPTIONCREATE USER(用於為其他使用者設定預設角色)ROLE_ADMIN(用於設定修改角色行為的系統變數)SYSTEM_VARIABLES_ADMIN(用於設定修改角色行為的系統變數)
CREATE ROLE 許可權是 CREATE USER 許可權的次級版本,允許您建立和管理角色。已經擁有 CREATE USER 許可權的賬戶會自動擁有管理角色所需的所有功能。
GRANT OPTION 許可權是分配許可權給角色所必需的。您必須為您想要分配給角色的任何許可權啟用 GRANT OPTION。
什麼是角色?
在 MySQL 中,角色是一個實體,它充當許可權的容器或集合。管理員可以像向用戶賬戶分配許可權一樣向角色分配許可權。然後,您可以將使用者賬戶新增為角色的成員,從而允許這些賬戶訪問與該角色關聯的許可權。
基本上,角色是捆綁不同相關許可權以簡化許可權管理的一種方式。與其透過分配單獨的許可權來確保每個使用者都擁有他們所需的精確訪問級別,不如使用命名的許可權分組,這樣您就可以管理更少、更容易理解的分配。
這在分配訪問級別時具有明顯的優勢,因為為使用者分配 developer、sysadmin 或 financeteam 角色比單獨管理數十個許可權更容易。它還可以快速同時調整多個賬戶的訪問許可權。如果您為銷售團隊建立了一個新資料庫,您可以將 salesteam 角色授予它,而不是跟蹤每個應該擁有訪問許可權的賬戶。
建立角色
如果您擁有 CREATE ROLE 許可權的賬戶,您可以使用 CREATE ROLE 命令管理角色。
MySQL 角色的語法是什麼?
角色名稱必須遵循特定格式才能被 MySQL 視為有效。在許多方面,它們與定義 MySQL 使用者賬戶所使用的格式類似,但有一些重要的區別。
角色遵循以下格式
'<role>'@'<host>'
像使用者一樣,角色有兩個組成部分:角色名稱和客戶端連線的主機。然而,MySQL 解釋這些組成部分的方式不同。
對於角色,名稱的 '<role>' 部分不能為空。不存在像使用者那樣的“匿名”角色概念。另一方面,省略 '<host>' 部分仍然允許,MySQL 將使用 % 作為主機。然而,在這種情況下,% 被解釋為字面字元,而不是萬用字元。
實際上,這意味著儘管角色名稱表面上與使用者賬戶名稱共享格式,但它們不像使用者賬戶那樣進行任何型別的評估,而只是一個具有兩個組成部分的標籤。它們確實有兩部分名稱的原因是,您可以建立既可以作為使用者又可以作為角色的使用者賬戶。當用作使用者時,這些組成部分受使用者管理文章中描述的特殊評估規則的約束,而當用作角色時,名稱只是使用字面組成部分名稱直接匹配。
由於這些規則,在許多情況下,管理員選擇僅使用 '<role>' 元件來定義角色。這導致 MySQL 用字面 % 字元替換 '<host>' 元件,從而有效地使該部分名稱不可見且無關緊要。如果您不打算將一個名稱同時用作使用者賬戶和角色,您也可以這樣做。
如何建立角色?
要建立新角色,請使用 CREATE ROLE 命令。
基本語法如下:
CREATE ROLE '<role>'@'<host>';
您還可以透過用逗號分隔每個角色名稱來同時建立多個角色
CREATE ROLE '<role_1>'@'<host>', '<role_2>'@'<host>', '<role_3>'@'<host>';
如果您指定的任何角色已存在於系統中,該命令將失敗並報錯。
為避免這種情況並使 MySQL 只發出警告,您可以在 CREATE ROLE 命令後、角色名稱前包含 IF NOT EXISTS 子句
CREATE ROLE IF NOT EXISTS '<role>'@'<host>';
如上所述,許多時候管理員為了簡化操作會省略角色名稱的 '<host>' 部分,隱式地將其設定為字面上的 % 字元。因此在實踐中,您的許多角色建立命令可能更像這樣:
CREATE ROLE '<role>';
如何授予角色許可權?
建立新角色後,您的首要任務通常是透過授予它們許可權來使它們具有意義。
您授予角色許可權的方式與您授予使用者賬戶許可權的方式相同。您提供希望授予的精確許可權,透過提供許可權有效的資料庫和資料庫物件來指定範圍,以及應授予許可權的實體——在本例中,是一個角色。
GRANT <privileges> ON <database>.<object> TO '<role>'@'<host>';
例如,要授予名為 readapp 的角色在 appdb 資料庫及其包含的所有物件上的 SELECT 許可權,您可以鍵入:
GRANT SELECT ON appdb.* TO 'readapp';
類似地,您可以透過鍵入以下內容,將相同資料庫的寫入許可權授予名為 writeapp 的角色:
GRANT SELECT,INSERT,UPDATE,DELETE ON appdb.* TO 'writeapp';
您可以像直接對使用者賬戶操作一樣,向角色授予和撤銷許可權。因此,如果需要調整您希望提供的訪問級別,您總是可以修改與角色關聯的許可權。
如何授予使用者角色成員身份?
將許可權新增到角色後,您可以開始將成員新增到角色中,以授予他們相關許可權。
為此,MySQL 使用與我們授予使用者和角色許可權時使用的 GRANT 命令不同的形式。然而,這種新形式將角色新增到使用者,允許使用者賬戶訪問賦予角色的所有許可權。
基本語法如下:
GRANT '<role>'@'<host>' TO '<user>'@'<host>';
例如,如果 'reports'@'localhost' 使用者需要能夠從 appdb 資料庫讀取資料以生成報告,我們可以將 readapp 角色新增到使用者賬戶,從而授予它選擇許可權
GRANT 'readapp' TO 'reports'@'localhost';
同樣,要賦予 'appuser'@'localhost' 管理同一資料庫中資料的能力,我們可以將該使用者設定為 writeapp 角色的成員
GRANT 'writeapp' TO 'appuser'@'localhost';
'appuser'@'localhost' 賬戶現在將具有從資料庫插入、更新和刪除資料的能力。如果新的許可權被新增到 writeapp 角色,'appuser'@'localhost' 賬戶將立即獲得這些許可權。
如何自動授予每個使用者某些角色?
有時,您可能希望系統中的每個使用者都擁有某些角色。您可以透過設定 mandatory_roles 變數來定義每個賬戶自動獲得哪些角色。
要修改 mandatory_roles 變數,您的使用者必須擁有 ROLE_ADMIN 和 SYSTEM_VARIABLES_ADMIN 許可權。您可以透過鍵入以下內容來設定希望自動授予每個使用者的角色:
SET PERSIST mandatory_roles = '`<role_1>`@`<host>`, `<role_2>`@`<host>`, `<role_3>`@`<host>`';
這裡,我們自動給系統中每個使用者三個角色。在設定系統變數時,mandatory_roles 的值必須是字串,因此我們將整個角色列表封裝在單引號中,並使用反引號引用單個角色元件。
您不能將具有 SYSTEM_USER 許可權的角色新增到 mandatory_roles 列表中。這是一項安全措施,旨在確保並非所有系統會話都自動成為系統會話。
如何使用角色中的許可權?
一旦您授予使用者賬戶角色成員身份,如何使用它們呢?要訪問透過角色授予賬戶的許可權,它必須被啟用。
檢視當前活動的角色
在啟用新角色之前,您可以檢查當前使用者會話中哪些角色處於活動狀態。
要檢視您會話中的活動角色,請鍵入:
SELECT CURRENT_ROLE()
輸出將顯示當前會話中零個或多個活動角色。與這些角色關聯的許可權將增加您被允許執行的操作。
如何啟用會話的角色
要更改會話期間活動的那些角色,請使用 SET ROLE 命令。您可以透過多種不同方式使用此命令。
基本語法如下:
SET ROLE '<rolename>'@'<host>';
這將啟用所討論的角色。重要的是要注意,任何先前活動但未在 SET ROLE 命令中提及的角色現在將被停用。
要同時啟用多個角色,請用逗號分隔每個角色
SET ROLE '<role_1>'@'<host>', '<role_2>'@'<host>', '<role_3>'@'<host>';
要啟用已授予您賬戶的所有角色,您可以指定 ALL 而不是特定角色
SET ROLE ALL;
您還可以透過使用 ALL EXCEPT 來告訴 MySQL 啟用除特定角色之外的所有角色
SET ROLL ALL EXCEPT '<role_1>'@'<host>';
另一個選項是透過指定 NONE 來停用您賬戶上的所有角色
SET ROLE NONE
這將停用您會話中的所有使用者角色,只為您提供專門分配給您使用者賬戶的許可權。
要返回為您的賬戶定義的預設角色列表,請使用 DEFAULT 關鍵字
SET ROLE DEFAULT
如何為使用者賬戶定義預設角色
當您以使用者身份登入時自動啟用的角色以及當您使用 SET ROLE DEFAULT 時重新啟用的角色是可配置的。
要定義預設啟用的角色,請使用 SET DEFAULT ROLE 命令,類似於您使用 SET ROLE 命令的方式
SET DEFAULT ROLE '<role_1>'@'<host>';
這將設定您自己賬戶登入時或使用 SET ROLE DEFAULT 時將自動啟用的預設角色。
如果您的使用者擁有 CREATE USER 許可權,您可以為其他賬戶設定預設角色
SET DEFAULT ROLE ALL TO '<user>'@'<host>';
這裡,我們指定 '<user>'@'<host>' 賬戶應在認證時自動啟用其所有角色。
此語法還可以用於透過逗號分隔每個使用者來為多個賬戶定義預設角色
SET DEFAULT ROLE ALL TO '<user_1>'@'<host>', '<user_2>'@'<host>';
預設情況下為所有使用者啟用所有角色
如果您希望您的 MySQL 伺服器上的所有賬戶預設啟用其所有角色,您可以更改系統設定來實現這一點。
當 activate_all_roles_on_login 變數設定為 true 時,MySQL 將在登入時自動啟用與賬戶關聯的所有角色。這會覆蓋 SET DEFAULT ROLE 指定的設定。
要啟用此功能,您必須擁有 SYSTEM_VARIABLES_ADMIN 和 ROLE_ADMIN 許可權。透過鍵入以下內容啟用該功能:
SET PERSIST activate_all_roles_on_login = ON;
這將導致使用者賬戶在登入時自動啟用所有角色。然而,SET ROLE DEFAULT 仍然允許您僅啟用與賬戶關聯的預設角色。
顯示從角色獲得的現有許可權
要了解您的賬戶有哪些可用許可權,您可以使用 SHOW GRANTS 命令。
要檢查使用者啟用的授權,請鍵入
SHOW GRANTS FOR '<user>'@'<host>';
輸出將顯示直接分配給使用者賬戶的所有許可權以及該使用者所屬的所有角色。
在瞭解賬戶所屬的角色後,您可以透過鍵入以下內容來檢查該角色為使用者提供的許可權:
SHOW GRANTS FOR '<user>'@'<host>' USING '<role>'@'<host>';
例如,要檢查 'reports'@'localhost' 使用者的許可權,包括其在 readapp 角色中的成員身份所授予的許可權,您可以使用:
SHOW GRANTS FOR 'reports'@'localhost' USING 'readapp';
這將顯示明確授予 'reports'@'localhost' 使用者賬戶的所有許可權以及由 readapp 角色新增的許可權。
撤銷使用者的角色
那麼,當您想從使用者中移除一個角色時會發生什麼呢?類似於 GRANT 命令可以向用戶或角色新增新許可權,或者向用戶新增角色一樣,REVOKE 命令可以從使用者或角色中移除許可權,並且還可以從使用者中移除角色成員資格。
從使用者賬戶中移除角色的基本語法如下所示
REVOKE '<role>' FROM '<user>'@'<host>';
執行這樣的語句後,使用者將不再擁有透過角色授予的許可權。
例如,我們可以透過鍵入以下內容,從 'appuser'@'localhost' 使用者賬戶中撤銷 writeapp 角色:
REVOKE 'writeapp' FROM 'appuser'@'localhost';
然而,如果使用者透過其他方式(無論是直接授予還是透過不同角色的成員身份授予)獲得了許可權,他們仍將擁有該許可權。因此,如果 'appuser'@'localhost' 使用者也是我們之前授予的 readapp 角色的成員,他們仍將擁有 appdb 資料庫上的 SELECT 許可權。
結論
在您的 MySQL 資料庫中使用角色來分配許可權可以幫助簡化訪問控制系統的管理開銷和複雜性。與直接授予許多不同許可權相比,使用角色可以更輕鬆地確保具有相同職責的使用者擁有相同的許可權。
同樣,角色允許您明確許可權授予背後的意圖。透過精心選擇的角色名稱,可以幫助區分不同訪問原因,而不是在沒有任何評論的情況下向賬戶授予大量許可權。透過花時間提前建立和組織角色,您將能夠更直接地管理使用者對資料不同部分的訪問,從而在長期內獲得益處。
常見問題
要執行重新整理許可權操作,告訴伺服器重新載入授權表,您可以發出 FLUSH PRIVILEGES 語句。
這也可以透過執行 mysqladmin flush-privileges 或 mysqladmin reload 命令來完成。
您可以使用 ALL 或 ALL PRIVILEGES 簡寫形式,以特定範圍將完整許可權分配給使用者。
以下語法將授予 'salesadmin'@'localhost' 使用者與 sales 資料庫相關的、您使用者能夠授予的所有許可權。
GRANT ALL PRIVILEGES ON sales.* TO 'salesadmin'@'localhost';
要全域性授予使用者只讀許可權,您可以使用萬用字元表示作用域元件中的資料庫和資料庫物件部分。
基本語法如下:
GRANT SELECT ON *.* TO 'sally'@localhost';
要將只讀授權的範圍限制為單個數據庫,請將點左側的萬用字元替換為資料庫名稱
GRANT SELECT ON account.* TO 'meredith'@'localhost';
同樣,要僅授予對資料庫中特定表的訪問許可權,請使用以下命令
GRANT SELECT ON account.revenue TO 'meredith'@'localhost';
要在 MySQL 中建立一個新的 root 或超級使用者賬戶,您必須使用 GRANT ALL PRIVILEGES 語句為其提供對資料庫中所有內容的完全 root 訪問許可權。
基本語法如下:
GRANT ALL PRIVILEGES ON *.* TO 'user_name'@'localhost' WITH GRANT OPTION;
要了解您的賬戶有哪些可用許可權,您可以使用 SHOW GRANTS 命令。
要檢查使用者啟用的授權,請鍵入
SHOW GRANTS FOR '<user>'@'<host>';
在瞭解賬戶所屬的角色後,您可以透過鍵入以下內容來檢查該角色為使用者提供的許可權:
SHOW GRANTS FOR '<user>'@'<host>' USING '<role>'@'<host>';
