分享到

引言

認證和授權是管理和保護 MySQL 伺服器的重要考量。認證(有時縮寫為“authn”)是指驗證客戶端是否被允許以特定使用者身份連線的策略和機制類別。授權(有時縮寫為“authz”)是在認證之後發生的過程,用於確定一個賬戶被允許執行哪些操作。

在本指南中,我們將探討 MySQL 為管理此訪問控制系統而提供的概念和元件。我們將討論使用者、角色、認證方法和許可權之間的相互作用,它們共同解決了如何在 MySQL 資料庫伺服器上控制誰可以執行什麼操作的問題。

MySQL 如何配置認證和授權?

MySQL 透過多種不同的相關係統來管理其認證和授權要求。廣義上講,其組成部分是

  • 使用者: 使用者是在 MySQL 伺服器上配置的獨立賬戶,其功能是身份。這些身份可以與認證方法結合,允許客戶端以該使用者身份連線,並且可以被授予許可權,以允許他們以不同粒度級別訪問和控制不同的資料庫物件。MySQL 中的使用者由一個 User 名稱和一個使用者連線的 Host 組成。相同的 User 名稱從不同的 Host 連線被視為不同的使用者。
  • 認證方法: 認證方法是確定連線客戶端是否應該被允許使用特定使用者賬戶的方式。這些方法通常涉及接受和驗證客戶端提供的密碼,但也有其他認證方法可用。
  • 許可權: 使用者的能力和訪問級別由直接授予他們、透過角色成員資格或透過物件所有權授予的許可權定義。這些許可權在各種範圍內定義,並針對使用者嘗試的每個操作進行檢查。
  • 角色: 實際上,角色是可以應用於使用者的許可權集合。將相關許可權組新增到角色中,然後透過角色成員資格分配這些許可權可以簡化許可權管理。

實際的訪問控制過程分為兩個不同的部分。首先,客戶端以特定使用者身份向伺服器進行認證。之後,每個操作都會根據使用者的授權許可權進行檢查,以確定是允許還是拒絕每個請求。

第一部分:認證

MySQL 訪問控制系統的第一階段是認證連線。MySQL 根據以下因素決定是否接受連線請求

  • 您是否可以正確認證為所請求的使用者賬戶
  • 該使用者賬戶是否在系統中被鎖定

如果您連線的使用者未被鎖定,並且您能夠正確認證,MySQL 將接受連線並允許您繼續訪問控制系統的第二部分。如果使用者被標記為鎖定,如果您的認證嘗試失敗,或者如果您提供的使用者無效,MySQL 將拒絕連線請求。

為執行這些功能,MySQL 會查詢其內部 mysql 資料庫中 user 表內的以下列

User

客戶端連線時使用的使用者名稱幫助 MySQL 確定如何認證使用者。當與下面的 Host 欄位結合時,它在 MySQL 中形成了完整且唯一的身份。

mysql.user 表中,一個空白的 User 值將匹配客戶端提供的任何使用者。但是,當這種情況發生時,客戶端在會話期間被視為匿名使用者。這在訪問控制的第二階段會產生影響,伺服器將針對匿名使用者而不是客戶端提供的使用者檢查操作。

Host

客戶端連線的主機被視為使用者身份的關鍵部分。在 MySQL 中,唯一身份是由使用者名稱和連線主機的組合形成的。

因此,來自 example.comuser1 被認為與來自 test.orguser1 是不同的。 User 欄位和 Host 欄位共同告訴 MySQL 嘗試認證哪個賬戶。

plugin

MySQL 使用 UserHost 確定要為連線請求檢索的正確記錄後,它會使用 plugin 欄位來決定如何認證客戶端。

使用者的 plugin 欄位定義了應該用於驗證使用者憑據的認證方法。預設外掛 caching_sha2_password 會將使用者的密碼與表中儲存的密碼雜湊版本進行核對。

authentication_string

對於“原生”認證外掛(僅使用 mysql.user 表中的資訊來認證使用者的外掛),authentication_string 列包含用於檢查使用者密碼的字串。大多數情況下,這是密碼的雜湊版本。如果原生外掛的 authentication_stringmysql.user 表中為空,則客戶端不得指定密碼才能成功認證。

對於使用外部系統進行認證的外掛,authentication_string 通常用於指定外部系統正確認證使用者所需的附加資訊(例如服務名稱、附加識別資訊等)。

account_locked

此列確定此特定使用者賬戶是否在系統中被鎖定。賬戶可以由資料庫管理員手動鎖定。賬戶必須解鎖才能繼續。

確定 mysql.user 表中行的優先順序

MySQL 使用上述五個欄位來確定是否接受連線。但是,在某些情況下,多個條目可能會匹配客戶端的連線。例如,客戶端可能未提供主機,或者 mysql.user 表可能包含沒有使用者的行。MySQL 需要一種方法來建立這些行的優先順序,以確定如何認證客戶端。

為此,MySQL 在伺服器啟動時或收到從磁碟重新載入資訊的訊號時,會將 mysql.user 表中的行讀入記憶體。在讀取行的同時,它還會根據特異性對它們進行排序,以便表中的行從最具體到最不具體進行排序。

首先,MySQL 根據 Host 列的特異性對行進行排序。 Host 由完整域名或 IP 地址組成的行排在最前面,其次是 Host 欄位中使用萬用字元的行(將僅包含萬用字元 % 的行放在最後,作為最不具體的條目),最後是 Host 為空的行。

MySQL 使用 User 列作為次要排序欄位。這意味著如果兩行具有相同的 Host 特異性,則 User 條目更具體的那行將被優先處理。 User 欄位中不允許使用萬用字元。

The User 欄位由以下之一組成

  • 必須與提供的使用者名稱完全匹配的字串,
  • 一個空白欄位,它將匹配客戶端提供的任何使用者名稱,但會以匿名使用者身份繼續會話

MySQL 將只使用 mysql.user 表中的最多一行來認證客戶端連線。這意味著如果認證失敗或匹配到錯誤的行,它將不會檢查可能正確認證的替代方案。為了確定用於認證客戶端連線請求的行,MySQL 從排序列表的頂部開始。它按順序檢查每一行,並使用它找到的第一個與客戶端連線匹配的行。

如果您不注意上述排序順序,這可能會產生一些令人驚訝的影響。例如,包含 Host 值但沒有 User 的行總是優先於包含 User 值但沒有 Host 的行被選中。理解這個排序系統將幫助您避免一整類認證問題。

如果您在認證某個特定使用者時遇到問題,請檢查是否存在更具體的匹配條目。如果您能夠連線,但無法執行您認為應該能夠執行的操作,請驗證 MySQL 是否允許您以您請求的使用者名稱而不是匿名使用者身份訪問,這可能如上所述發生。

此命令將打印出您當前認證的使用者:

SELECT CURRENT_USER()

第二部分:授權

客戶端憑據認證成功後,MySQL 建立連線並進入訪問控制系統的第二部分以確定授權。MySQL 授權是一個持續進行的過程,它根據使用者賬戶的特定許可權檢查每個命令。如果命令在使用者許可權範圍內,則允許該操作。否則,伺服器將拒絕該請求。

不同型別的許可權

為了解釋某些許可權為何儲存在特定位置,有必要討論 MySQL 中不同型別的許可權。

許可權範圍

許可權可以在不同的範圍級別進行分配,這決定了所授予許可權的作用區域。某些許可權僅在特定範圍有效,而其他許可權可以根據您希望啟用的粒度在不同範圍進行分配。

全域性許可權是不與特定資料庫繫結的許可權。它們在整個 MySQL 伺服器中有效。許多全域性許可權與系統管理相關,並與系統管理職責而非直接資料管理相關聯。

資料庫許可權與 MySQL 伺服器中的特定資料庫繫結。在資料庫範圍授予的許可權影響使用者可以對資料庫以及其中包含的任何資料庫物件(如表)執行的操作。資料庫許可權可以授予特定資料庫,也可以普遍授予所有資料庫。

物件許可權允許您控制資料庫中的表、索引等。這些許可權可以授予特定物件、特定資料庫中所有某種型別的物件,或者授予整個伺服器中所有某種型別的物件。

靜態許可權與動態許可權

在內部,許可權可以分為靜態許可權和動態許可權。

靜態許可權是內建在伺服器中的,無法登出(停用)。無論伺服器上啟用了哪些元件,這些許可權始終可用。通常,靜態許可權是適用於所有或大多數系統的基本許可權(例如,讀取或寫入資料的能力)。

另一方面,動態許可權取決於定義它們的外掛或元件的可用性。這些許可權可以在執行時註冊或登出,以影響其可用性。未註冊的許可權無法授予,但已授予的許可權會在啟動時自動註冊。動態許可權始終是全域性範圍的(適用於整個 MySQL 伺服器)。

許可權定義位置

MySQL 的許可權在內部 mysql 系統資料庫的許多不同表中定義。這些內部定義的許可權組合將決定使用者針對某個操作或資料庫物件的特定許可權。 mysql 資料庫中的以下表涉及許可權定義

  • user: 除了為認證定義使用者賬戶外,user 表還定義了每個使用者的靜態全域性許可權。這些許可權適用於整個 MySQL 伺服器,不受任何外掛或元件可用性的影響。
  • global_grants: global_grants 表定義了每個使用者的動態全域性許可權。任何由外掛或元件定義的許可權都會註冊到此表中。
  • db: db 表定義了資料庫級別的許可權。db 表與 user 表一樣匹配使用者的 UserHost 值,但它還有一個名為 Db 的列,用於定義該行的資料庫範圍。
  • tables_priv: tables_priv 表以類似於 db 表定義資料庫許可權的方式定義表級許可權。為了啟用表級範圍,除了 UserHostDb 之外,還提供了一個名為 Table_name 的列。
  • columns_priv: columns_priv 表比 tables_priv 表更進一步,它決定了列級別的訪問。為了增加這種額外的粒度,除了 tables_priv 表中可用的列之外,還包含了一個名為 Column_name 的列。
  • procs_priv: procs_priv 表定義了執行儲存過程和函式的許可權。它使用 UserHostDbRoutine_nameRoutine_type 列來限定使用者對不同型別程序的許可權範圍。
  • proxies_priv: proxies_priv 表定義了使用者的代理許可權。代理允許一個使用者扮演另一個使用者,繼承其許可權。proxies_priv 表使用 UserHost 列來匹配使用者,然後使用名為 Proxied_hostProxied_user 的獨立列來定義匹配的使用者可以扮演誰。

這些表的 使用者賬戶匹配功能與我們之前描述的 mysql.user 表讀入記憶體並排序的方式類似。

要顯示當前與使用者關聯的授權,您可以輸入

SHOW GRANTS FOR '<user>'@'<host>';

您還可以使用以下命令檢視非許可權賬戶屬性

SHOW CREATE USER '<user>'@'<host>';

角色

角色是與授權過程相關的另一個元件。角色是管理員建立的命名許可權捆綁包,旨在簡化許可權管理。一旦將一組許可權授予某個角色,您就可以透過將使用者新增為該角色的成員來授予他們這些許可權。

因此,如果您想讓多個使用者能夠在一個特定表中插入和更新值,您可以建立一個具有這些許可權的角色。然後,您可以透過在該角色中新增或移除使用者來控制誰可以插入和更新該表。這為不同型別的使用者建立了明確定義的訪問級別,並有助於確保訪問級別在所有賬戶之間保持一致。

角色對它們所涉及的認證過程複雜性的影響很小。然而,我們在此提及它們,是因為它們作為管理許可權的一種方式非常有用。

結論

認證和授權是 MySQL 安全方法的重要要求。它們共同作為系統的訪問控制控制器,透過規範誰可以連線到伺服器、他們可以檢視和互動哪些結構以及他們可以訪問哪些資料。瞭解這些系統如何互動可以幫助您配置安全的策略,從而保護您的資料,同時不阻礙所有合法操作。

關於作者
Justin Ellingwood

賈斯汀·埃林伍德 (Justin Ellingwood)

賈斯汀自 2013 年以來一直撰寫有關資料庫、Linux、基礎設施和開發者工具的文章。他目前與妻子和兩隻兔子住在柏林。他通常不需要以第三人稱寫作,這讓所有相關方都鬆了一口氣。
© . This site is unofficial and not affiliated with Prisma Data, Inc.