MySQL權限系統保證所有的用戶只執行允許做的事情。當你連接MySQL服務器時,你的身份由你從那兒連接的主機和你指定的用戶名來決定。連接后發出請求后,系統根據你的身份和你想做什么來授予權限。
MySQL在認定身份中考慮你的主機名和用戶名字,是因為幾乎沒有原因假定一個給定的用戶在因特網上屬于同一個人。例如,從office.com連接的用戶joe不一定和從elsewhere.com連接的joe是同一個人。MySQL通過允許你區分在不同的主機上碰巧有同樣名字的用戶來處理它:你可以對joe從office.com進行的連接授與一個權限集,而為joe從elsewhere.com的連接授予一個不同的權限集。
MySQL存取控制包含2個階段:
- 階段1:服務器檢查是否允許你連接。
- 階段2:假定你能連接,服務器檢查你發出的每個請求。看你是否有足夠的權限實施它。例如,如果你從數據庫表中選擇(select)行或從數據庫刪除表,服務器確定你對表有SELECT權限或對數據庫有DROP權限。
如果連接時你的權限被更改了(通過你和其它人),這些更改不一定立即對你發出的下一個語句生效。詳情參見5.7.7節,“權限更改何時生效”。
服務器在mysql數據庫的 授權表中保存權限信息(即在mysql數據庫中)。當MySQL服務器啟動時將這些表的內容讀入內存,在5.7.7節,“權限更改何時生效”的環境下重新讀取它們。訪問控制決策取決于內存中的 授權表的份數。
一般情況,你通過GRANT和REVOKE語句間接來操作 授權表的內容,設置賬戶并控制個人的權限。參見13.5.1.3節,“GRANT和REVOKE語法”。下面討論了 授權表的結構以及服務器與客戶端交互操作時如何使用其內容。
服務器在存取控制的兩個階段使用mysql數據庫中的user、db和host表,這些授權表中的列如下:
表名 |
user |
db |
host |
列范圍 |
Host |
Host |
Host |
|
User |
Db |
Db |
|
Password |
User |
|
權限列 |
Select_priv |
Select_priv |
Select_priv |
|
Insert_priv |
Insert_priv |
Insert_priv |
|
Update_priv |
Update_priv |
Update_priv |
|
Delete_priv |
Delete_priv |
Delete_priv |
|
Index_priv |
Index_priv |
Index_priv |
|
Alter_priv |
Alter_priv |
Alter_priv |
|
Create_priv |
Create_priv |
Create_priv |
|
Drop_priv |
Drop_priv |
Drop_priv |
|
Grant_priv |
Grant_priv |
Grant_priv |
|
Create_view_priv |
Create_view_priv |
Create_view_priv |
|
Show_view_priv |
Show_view_priv |
Show_view_priv |
|
Create_routine_priv |
Create_routine_priv |
|
|
Alter_routine_priv |
Alter_routine_priv |
|
|
References_priv |
References_priv |
References_priv |
|
Reload_priv |
|
|
|
Shutdown_priv |
|
|
|
Process_priv |
|
|
|
File_priv |
|
|
|
Show_db_priv |
|
|
|
Super_priv |
|
|
|
Create_tmp_table_priv |
Create_tmp_table_priv |
Create_tmp_table_priv |
|
Lock_tables_priv |
Lock_tables_priv |
Lock_tables_priv |
|
Execute_priv |
|
|
|
Repl_slave_priv |
|
|
|
Repl_client_priv |
|
|
安全列 |
ssl_type |
|
|
|
ssl_cipher |
|
|
|
x509_issuer |
|
|
|
x509_subject |
|
|
資源控制列 |
max_questions |
|
|
|
max_updates |
|
|
|
max_connections |
|
|
|
max_user_connections |
|
|
對存取控制的第二階段(請求證實),服務器執行請求驗證以確保每個客戶端有充分的權限滿足各需求。除了user、db和host授權表,如果請求涉及表,服務器可以另外參考tables_priv和columns_priv表。tables_priv和columns_priv表可以對表和列提供更精確的權限控制。這些表的列如下:
表名 |
tables_priv |
columns_priv |
范圍列 |
Host |
Host |
|
Db |
Db |
|
User |
User |
|
Table_name |
Table_name |
|
|
Column_name |
權限列 |
Table_priv |
Column_priv |
|
Column_priv |
|
其它列 |
Timestamp |
Timestamp |
|
Grantor |
|
Timestamp和Grantor列當前還未使用,這兒不再進一步討論。
為了對涉及保存程序的請求進行驗證,服務器將查閱procs_priv表。該表具有以下列:
表名 |
procs_priv |
范圍列 |
Host |
|
Db |
|
User |
|
Routine_name |
|
Routine_type |
權限列 |
Proc_priv |
其它列 |
Timestamp |
|
Grantor |
Routine_type列為ENUM列,值為'FUNCTION'或'PROCEDURE',表示行所指的程序類型。該列允許為同名函數和程序單獨授權。
Timestamp和Grantor列當前還未使用,這兒不再進一步討論。
每個授權表包含范圍列和權限列:
l 范圍列決定表中每個條目(行)的范圍,即,行適用的上下文。例如, 一個user表行的Host和User值為'thomas.loc.gov'和'bob',將被用于證實來自主機thomas.loc.gov的bob對服務器的連接。同樣,一個db表行的Host、User和Db列的值是'thomas.loc.gov'、'bob'和'reports'將用在bob從主機thomas.loc.gov聯接訪問reports數據庫的時候。tables_priv和columns_priv表包含范圍列,指出每個行適用的表或表/列的組合。procs_priv范圍列指出每個行適用的保存程序。
對于檢查存取的用途,比較Host值是忽略大小寫的。User、Password、Db和Table_name值是區分大小寫的。Column_name值在MySQL3.22.12或以后版本是忽略大小寫的。
l 權限列指出由一個表行授予的權限,即,可實施什么操作。服務器組合各種的授權表的信息形成一個用戶權限的完整描述。為此使用的規則在5.7.6節,“訪問控制, 階段2:請求核實”描述。
范圍列包含字符串,如下所述;每個列的默認值是空字符串:
列名 |
類型 |
Host |
CHAR(60) |
User |
CHAR(16) |
Password |
CHAR(16) |
Db |
CHAR(64) |
Table_name |
CHAR(64) |
Column_name |
CHAR(64) |
Routine_name |
CHAR(64) |
為了訪問檢查目的,Host值的比較對大小寫不敏感。User、Password、Db和Table_name值對大小寫敏感。Column_name值對大小寫不敏感。
在user、db和host表中,所有權限列于單獨的列內,被聲明為ENUM('N','Y') DEFAULT 'N'。換句話說,每一個權限都可以被禁用和啟用,并且 默認是禁用。
在tables_priv、columns_priv和procs_priv表中,權限列被聲明為SET列。這些列的值可以包含該表控制的權限的組合:
表名 |
列名 |
可能的設置元素 |
tables_priv |
Table_priv |
'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter' |
tables_priv |
Column_priv |
'Select', 'Insert', 'Update', 'References' |
columns_priv |
Column_priv |
'Select', 'Insert', 'Update', 'References' |
procs_priv |
Proc_priv |
'Execute', 'Alter Routine', 'Grant' |
簡單地說,服務器使用這樣的授權表:
· user表范圍列決定是否允許或拒絕到來的連接。對于允許的連接,user表授予的權限指出用戶的全局(超級用戶)權限。這些權限適用于服務器上的all數據庫。
· db表范圍列決定用戶能從哪個主機存取哪個數據庫。權限列決定允許哪個操作。授予的數據庫級別的權限適用于數據庫和它的表。
· 當你想要一個給定的db表行應用于若干主機時,db和host表一起使用。例如,如果你想要一個用戶能在你的網絡從若干主機使用一個數據庫,在用戶的db表行的Host值設為空值,然后將那些主機的每一個移入host表。這個機制詳細描述在5.7.6節,“訪問控制, 階段2:請求核實”。
注釋:host表不受GRANT和REVOKE語句的影響。大多數MySQL安裝根本不需要使用該表。
· tables_priv和columns_priv表類似于db表,但是更精致:它們在表和列級應用而非在數據庫級。授予表級別的權限適用于表和所有它的列。授予列級別的權限只適用于專用列。
· procs_priv表適用于保存的程序。授予程序級別的權限只適用于單個程序。
管理權限(例如RELOAD或SHUTDOWN等等)僅在user表中被指定。這是因為管理性操作是服務器本身的操作并且不是特定數據庫,因此沒有理由在其他授權表中列出這樣的權限。事實上,只需要查詢user表來決定你是否執行一個管理操作。
FILE權限也僅在user表中指定。它不是管理性權限,但你在服務器主機上讀或寫文件的能力與你正在存取的數據庫無關。
當mysqld服務器啟動時,將授權表的內容讀入到內存中。你可以通過FLUSH PRIVILEGES語句或執行mysqladmin flush-privileges或mysqladmin reload命令讓它重新讀取表。對授權表的更改生效在5.7.7節,“權限更改何時生效”描述。
當你修改授權表的內容時,確保你按你想要的方式更改權限設置是一個好主意。要檢查給定賬戶的權限,使用SHOW GRANTS語句。例如,要檢查Host和User值分別為pc84.example.com和bob的賬戶所授予的權限,應通過語句:
mysql> SHOW GRANTS FOR 'bob'@'pc84.example.com';
一個有用的診斷工具是mysqlaccess腳本,由Carlier Yves 提供給MySQL分發。使用--help選項調用mysqlaccess查明它怎樣工作。注意:mysqlaccess僅用user、db和host表檢查存取。它不檢查tables_priv、columns_priv或procs_priv表中指定的表、列和程序級權限。
對于診斷權限相關的問題的其它幫助,參見5.7.8節,“拒絕訪問錯誤的原因”。對于安全問題常規建議,參見5.6節,“一般安全問題”。