MySQL權限系統保證所有的使用者可以嚴格地做他們假定被允許做的事情。當你連接配接一個MySQL伺服器時, 你的身份由你從那連接配接的主機和你指定的使用者名來決定,系統根據你的身份和你想做什麼來授予權限。
MySQL在認定身份中考慮你的主機名和使用者名字,是因為有很小的原因假定一個給定的使用者在網際網路上屬于同一個人。例如,使用者從whitehouse.gov連接配接的bill不必和從mosoft.com連接配接bill是同一個人。 MySQL通過允許你區分在不同的主機上碰巧有同樣名字使用者來處理它:你可以對從whitehouse.gov連接配接授與bill一個權限集,而為從microsoft.com的連接配接授予一個不同的權限集。
MySQL存取控制包含2個階段:
階段1:伺服器檢查你是否允許連接配接。
階段2:假定你能連接配接,伺服器檢查你發出的每個請求。看你是否有足夠的權限實施它。例如,如果你從資料庫中一個表精選(select)行或從資料庫抛棄一個表,伺服器确定你對表有select權限或對資料庫有drop權限。
伺服器在存取控制的兩個階段使用在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
Reload_priv
Shutdown_priv
Process_priv
File_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
每個授權表包含範圍字段和權限字段。
範圍字段決定表中每個條目的範圍,即,條目适用的上下文。例如, 一個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表包含範圍字段,指出每個條目适用的表或表/列的組合。
對于檢查存取的用途,比較Host值是忽略大小寫的。User、Password、Db和Table_name值是區分大小寫的。Column_name值在MySQL3.22.12或以後版本是忽略大小寫的。
權限字段指出由一個表條目授予的權限,即,可實施什麼操作。伺服器組合各種的授權表的資訊形成一個使用者權限的完整描述。為此使用的規則在6.8 存取控制, 階段2:請求證明描述。
範圍字段是字元串,如下所述;每個字段的預設值是空字元串:
字段名 類型
Host CHAR(60)
User CHAR(16)
Password CHAR(16)
Db CHAR(64) (tables_priv和columns_priv表為CHAR(60))
在user、db和host表中,所有權限字段被聲明為ENUM(''N'',''Y'')--每一個都可有值''N''或''Y'',并且預設值是''N''.
在tables_priv和columns_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''
簡單地說,伺服器使用這樣的授權表:
user表範圍字段決定是否允許或拒絕到來的連接配接。對于允許的連接配接,權限字段指出使用者的全局(超級使用者)權限。
db和host表一起使用:
db表範圍字段決定使用者能從哪個主機存取哪個資料庫。權限字段決定允許哪個操作。
當你想要一個給定的db條目應用于若幹主機時,host表作為db表的擴充被使用。例如,如果你想要一個使用者能在你的網絡從若幹主機使用一個資料庫,在使用者的db表的Host條目設為空值,然後将那些主機的每一個移入host表。這個機制較長的描述在6.8 存取控制, 階段2:請求證明。
tables_priv和columns_priv表類似于db表,但是更精緻:他們在表和列級應用而非在資料庫級。
注意管理權限(reload, shutdown, 等等)僅在user表中被指定。這是因為管理性操作是伺服器本身的操作并且不是特定資料庫,是以沒有理由在其他授權表中列出這樣的權限。事實上,隻需要請教user表來決定你是否執行一個管理操作。
file權限也僅在user表中指定。它不是管理性權限,但你讀或謝在伺服器主機上的檔案的的能力獨立于你正在存取的資料庫。
當mysqld伺服器啟動時,讀取一次授權
MySQL教程是:Mysql權限系統工作原理。表内容。對授權表的更改生效在6.9 權限更改何時生效描述。
當你修改授權表的内容時,確定你按你想要的方式更改權限設定是一個好主意。為幫助診斷問題,見6.13 “存取拒絕引起”錯誤的原因。對于安全問題上的忠告,見6.14 怎麼對使MySQL安全對抗解密高手。
一個有用的診斷工具是mysqlaccess腳本,由Carlier Yves 提供給MySQL分發。使用--help選項調用mysqlaccess查明它怎樣工作。注意:mysqlaccess僅用user、db和host表僅檢查存取。它不檢查表或列級權限。
6.7 存取控制, 階段1:連接配接證明
當你試圖聯接一個MySQL伺服器時,伺服器基于你的身份和你是否能通過供應正确的密碼驗證身份來接受或拒絕連接配接。如果不是,伺服器完全具結你的存取,否則,伺服器接受連接配接,然後進入階段2并且等待請求。
你的身份基于2個資訊:
你從那個主機連接配接
你的MySQL使用者名
身份檢查使用3個user表(Host, User和Password)範圍字段執行。伺服器隻有在一個user表條目比對你的主機名和使用者名并且你提供了正确的密碼時才接受連接配接。
在user表範圍字段可以如下被指定:
一個Host值可以是主機名或一個IP數字,或''localhost''指出本地主機。
你可以在Host字段裡使用通配符字元“%”和“_”。
一個Host值''%''比對任何主機名,一個空白Host值等價于''%''。注意這些值比對能建立一個連接配接到你的伺服器的任何主機!
通配符字元在User字段中不允許,但是你能指定空白的值,它比對任何名字。如果user表比對到來的連接配接的條目有一個空白的使用者名,使用者被認為是匿名使用者(沒有名字的使用者),而非客戶實際指定的名字。這意味着一個空白的使用者名被用于在連接配接期間的進一步的存取檢查(即,在階段2期間)。
Password字段可以是空白的。這不意味着比對任何密碼,它意味着使用者必須不指定一個密碼進行連接配接。
非空白Password值代表加密的密碼。 MySQL不以任何人可以看的純文字格式存儲密碼,相反,正在試圖聯接的一個使用者提供的密碼被加密(使用PASSWORD()函數),并且與存儲了user表中的已經加密的版本比較。如果他們比對,密碼是正确的。
下面的例子顯示出各種user表中Host和User條目的值的組合如何應用于到來的連接配接:
Host 值 User 值 被條目比對的連接配接
''thomas.loc.gov'' ''fred'' fred, 從thomas.loc.gov 連接配接
''thomas.loc.gov'' '''' 任何使用者, 從thomas.loc.gov連接配接
''%'' ''fred'' fred, 從任何主機連接配接
''%'' '''' 任何使用者, 從任何主機連接配接
''%.loc.gov'' ''fred'' fred, 從在loc.gov域的任何主機連接配接
''x.y.%'' ''fred'' fred, 從x.y.net、x.y.com,x.y.edu等聯接。(這或許無用)
''144.155.166.177'' ''fred'' fred, 從有144.155.166.177 IP 位址的主機連接配接
''144.155.166.%'' ''fred'' fred, 從144.155.166 C類子網的任何主機連接配接
既然你能在Host字段使用IP通配符值(例如,''144.155.166.%''比對在一個子網上的每台主機),有可能某人可能企圖探究這種能力,通過命名一台主機為144.155.166.somewhere.com。為了阻止這樣的企圖,MySQL不允許比對以數字和一個點起始的主機名,這樣,如果你用一個命名為類似1.2.foo.com的主機,它的名字決不會比對授權表中Host列。隻有一個IP數字能比對IP通配符值。
一個到來的連接配接可以被在user表中的超過一個條目比對。例如,一個由fred從thomas.loc.gov的連接配接比對多個條目如上所述。如果超過一個比對,伺服器怎麼選擇使用哪個條目呢?伺服器在啟動時讀入user表後通過排序來解決這個問題,然後當一個使用者試圖連接配接時,以排序的順序浏覽條目,第一個比對的條目被使用。
user表排序工作如下,假定user表看起來像這樣:
+-----------+----------+-
| Host | User | ...
| % | root | ...
| % | jeffrey | ...
| localhost | root | ...
| localhost | | ...
當伺服器在表中讀取時,它以最特定的Host值為先的次序排列(''%''在Host列裡意味着“任何主機”并且是最不特定的)。有相同Host值的條目以最特定的User值為先的次序排列(一個空白User值意味着“任何使用者”并且是最不特定的)。最終排序的user表看起來像這樣:
當一個連接配接被嘗試時,伺服器浏覽排序的條目并使用找到的第一個比對。對于由jeffrey從localhost的一個連接配接,在Host列的''localhost''條目首先比對。那些有空白使用者名的條目比對連接配接的主機名和使用者名。(''%''/''jeffrey''條目也将比對,但是它不是在表中的第一比對。)
這是另外一個例子。假定user桌子看起來像這樣:
+----------------+----------+-
| Host | User | ...
| % | jeffrey | ...
| thomas.loc.gov | | ...
排序後的表看起來像這樣:
+---------------
MySQL教程是:Mysql權限系統工作原理。-+----------+-
一個由jeffrey從thomas.loc.gov的連接配接被第一個條目比對,而一個由jeffrey從whitehouse.gov的連接配接被第二個比對。
普遍的誤解是認為,對一個給定的使用者名,當伺服器試圖對連接配接尋找比對時,明确命名那個使用者的所有條目将首先被使用。這明顯不是事實。先前的例子說明了這點,在那裡一個由jeffrey從thomas.loc.gov的連接配接沒被包含''jeffrey''作為User字段值的條目比對,但是由沒有使用者名的題目比對!
如果你有伺服器連接配接的問題,列印出user表并且手工排序它看看第一個比對在哪兒進行。
6.8 存取控制,階段2:請求證明
一旦你建立了一個連接配接,伺服器進入階段2。對在此連接配接上進來的每個請求,伺服器檢查你是否有足夠的權限來執行它,它基于你希望執行的操作類型。這正是在授權表中的權限字段發揮作用的地方。這些權限可以來子user、db、host、tables_priv或columns_priv表的任何一個。授權表用GRANT和REVOKE指令操作。見7.26 GRANT和REVOKE 句法。(你可以發覺參考6.6 權限系統怎樣工作很有幫助,它列出了在每個權限表中呈現的字段。)
user表在一個全局基礎上授予賦予你的權限,該權限不管目前的資料庫是什麼均适用。例如,如果user表授予你delete權限, 你可以删除在伺服器主機上從任何資料庫删除行!換句話說,user表權限是超級使用者權限。隻把user表的權限授予超級使用者如伺服器或資料庫主管是明智的。對其他使用者,你應該把在user表中的權限設成''N''并且僅在一個特定資料庫的基礎上授權, 使用db和host表。
db和host表授予資料庫特定的權限。在範圍字段的值可以如下被指定:
通配符字元“%”和“_”可被用于兩個表的Host和Db字段。
在db表的''%''Host值意味着“任何主機”,在db表中一個空白Host值意味着“對進一步的資訊咨詢host表”。
在host表的一個''%''或空白Host值意味着“任何主機”。
在兩個表中的一個''%''或空白Db值意味着“任何資料庫”。
在兩個表中的一個空白User值比對匿名使用者。
db和host表在伺服器啟動時被讀取和排序(同時它讀user表)。db表在Host、Db和User範圍字段上排序,并且host表在Host和Db範圍字段上排序。對于user表,排序首先放置最特定的值然後最後最不特定的值,并且當伺服器尋找比對入條目時,它使用它找到的第一個比對。
tables_priv和columns_priv表授予表和列特定的權限。在範圍字段的值可以如下被指定:
通配符“%”和“_”可用在使用在兩個表的Host字段。
在兩個表中的一個''%''或空白Host意味着“任何主機”。
在兩個表中的Db、Table_name和Column_name字段不能包含通配符或空白。
tables_priv和columns_priv表在Host、Db和User字段上被排序。這類似于db表的排序,盡管因為隻有Host字段可以包含通配符,但排序更簡單。
請求證明程序在下面描述。(如果你熟悉存取檢查的源代碼,你會注意到這裡的描述與在代碼使用的算法略有不同。描述等價于代碼實際做的東西;它隻是不同于使解釋更簡單。)
對管理請求(shutdown、reload等等),伺服器僅檢查user表條目,因為那是唯一指定管理權限的表。如果條目許可請求的操作,存取被授權了,否則拒絕。例如,如果你想要執行mysqladmin shutdown,但是你的user表條目沒有為你授予shutdown權限,存取甚至不用檢查db或host表就被拒絕。(因為他們不包含Shutdown_priv行列,沒有這樣做的必要。)
對資料庫有關的請求(insert、update等等),伺服器首先通過查找user表條目來檢查使用者的全局(超級使用者)權限。如果條目允許請求的操作,存取被授權。如果在user表中全局權限不夠,伺服器通過檢查db和host表确定特定的使用者資料庫權限:
伺服器在db表的Host、Db和User字段上查找一個比對。 Host和User對應連接配接使用者的主機名和MySQL使用者名。Db字段對應使用者想要存取的資料庫。如果沒有Host和User的條目,存取被拒絕。
如果db表中的條目有一個比對而且它的Host字段不是空白的,該條目定義使用者的資料庫特定的權限。
如果比對的db表的條目的Host字段是空白的,它表示host表列舉主機應該被允許存取資料庫的主機。在這種情況下,在host表中作進一步查找以發現Host和Db字段上的比對。如果沒有host表條目比對,存取被拒絕。如果有比對,使用者資料庫特定的權限以在db和host表的條目的權限,即在兩個條目都是''Y''的權限的交集(而不是并集!)計算。(這樣你可以授予在db表條目中的一般權限,然後用host表條目按一個主機一個主機為基礎地有選擇地限制它們。)
在确定了由db和host表條目授予的資料庫特定的權限後,伺服器把他們加到由user表授予的全局權限中。如果結果允許請求的操作,存取被授權。否則,伺服器檢查在tables_priv和columns_priv表中的使用者的表和列權限并把它們加到使用者權限中。基于此結果允許或拒絕存取。
用布爾術語表示,前面關于一個使用者權限如何計算的描述可以這樣總結:
global privileges
OR (database privileges AND host privileges)
OR table privileges
OR column privileges
它可能不明顯,為什麼呢,如果全局user條目的權限最初發現對請求的操作不夠,伺服器以後把這些權限加到資料庫、表和列的特定權限。原因是一個請求可能要求超過一種類型的權限。例如,如果你執行一個INSERT ... SELECT語句,你就都要insert和select權限。你的權限必須如此以便user表條目授予一個權限而db表條目授予另一個。在這種情況下,你有必要的權限執行請求,但是伺服器不能自己把兩個表差別開來;兩個條目授予的權限必須組合起來。
host表能被用來維護一個“安全”伺服器清單。在TcX,host表包含一個在本地的網絡上所有的機器的表,這些被授予所有的權限。
你也可以使用host表指定不安全的主機。假定你有一台機器public.your.domain,它位于你不認為是安全的一個公共區域,你可以用下列的host表條目子允許除了那台機器外的網絡上所有主機的存取:
+--------------------+----+-
| Host | Db | ...
| public.your.domain | % | ... (所有權限設為 ''N'')
| %.your.domain | % | ... (所有權限設為 ''Y'')
當然,你應該總是測試你在授權表中的條目(例如,使用mysqlaccess)讓你確定你的存取權限實際上以你認為的方式被設定.
本文轉自holy2009 51CTO部落格,原文連結:http://blog.51cto.com/holy2010/370154