當你試圖連接MySQL服務器時,服務器基于你的身份以及你是否能通過供應正確的密碼驗證身份來接受或拒絕連接。如果不是,服務器完全拒絕你的訪問,否則,服務器接受連接,然后進入階段2并且等待請求。
你的身份基于2個信息:
- 你從那個主機連接
- 你的MySQL用戶名
身份檢查使用3個user表(Host, User和Password)范圍列執行。服務器只有在user表記錄的Host和User列匹配客戶端主機名和用戶名并且提供了正確的密碼時才接受連接。
在user表Host值的指定方法:
- Host值可以是主機名或IP號,或'localhost'指出本地主機。
- 你可以在Host列值使用通配符字符“%”和“_”。
- Host值'%'匹配任何主機名,空Host值等價于'%'。它們的含義與LIKE操作符的模式匹配操作相同。例如,'%'的Host值與所有主機名匹配,而'%.mysql.com'匹配mysql.com域的所有主機。
· 對于指定為IP號的Host值,你可以指定一個網絡掩碼,說明使用多少位地址位來評比網絡號。例如:
· mysql> GRANT ALL PRIVILEGES ON db.*
· -> -> TO david@'192.58.197.0/255.255.255.0';
允許david從任何客戶端用IP號client_ip來連接,下面的條件為真:
client_ip & netmask = host_ip
That is, for the GRANT statement just shown:
client_ip & 255.255.255.0 = 192.58.197.0
滿足該條件并可以連接MySQL服務器的IP號的范圍為192.58.197.0到192.58.197.255。
· 注釋:網絡掩碼只用來告訴服務器使用8、16、24或32位地址,例如:
· 192.0.0.0/255.0.0.0(192 A類網絡的任何地址)
· 192.168.0.0/255.255.0.0(192.168 A類網絡的任何地址)
· 192.168.1.0/255.255.255.0(192.168.1 C類網絡的任何地址)
· 192.168.1.1(只有該IP)
下面的網絡掩碼(28 位)無效:
192.168.0.1/255.255.255.240
· db表記錄中的空Host值表示它的權限應結合匹配客戶端名的host表中的行使用。通過AND(相與)而不是或(聯合)操作將權限組合到一起。你可以從5.7.6節,“訪問控制, 階段2:請求核實”找到關于host表的詳細信息。
其它grant表的空Host值與'%'相同。
既然你能在Host字段使用IP通配符值(例如,'144.155.166.%'匹配在一個子網上的每臺主機),有可能某人可能企圖探究這種能力,通過命名一臺主機為144.155.166.somewhere.com。為了阻止這樣的企圖,MySQL不允許匹配以數字和一個點起始的主機名,這樣,如果你用一個命名為類似1.2.foo.com的主機,它的名字決不會匹配授權表中的Host列。只有一個IP數字能匹配IP通配符值。
通配符字符在User列中不允許,但是你能指定空的值,它匹配任何名字。如果user表匹配的連接有一個空用戶名,用戶被認為是匿名用戶(沒有名字的用戶),而非客戶端實際指定的名字。這意味著一個空的用戶名被用于在連接期間的進一步的訪問檢查(即,在階段2期間)。
Password列可以是空的。這不是通配符,也不意味著匹配任何密碼,它意味著用戶必須不指定一個密碼進行連接。
user表中的非空Password值代表加密的密碼。MySQL不以任何人可以看的明文文本格式存儲密碼,相反,正在試圖聯接的用戶提供的密碼被加密(使用PASSWORD( )函數),在連接過程中使用加密的密碼檢查密碼是否正確。(加密后的密碼未通過連接即可實現)。從MySQL角度,加密的密碼是實際密碼,因此你不應讓其它人訪問它!特別是,絕對不要讓非管理用戶讀mysql數據庫中的表!
MySQL 5.1使用強鑒定方法(最先在MySQL 4.1中適用)在前面的版本中在連接進程中的密碼保護較好。即使TCP/IP包被截取或mysql數據庫 被捕獲也很安全。5.7.9節,“MySQL 4.1中的密碼哈希處理”中詳細討論了密碼加密。
下面的例子顯示出各種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類子網的任何主機連接 |
到來的連接中的客戶端名和用戶名可能與user表中的多行匹配。例如,由fred從thomas.loc.gov的連接匹配多個條目如上所述。
如果有多個匹配,服務器必須選擇使用哪個條目。按照下述方法解決問題:
l 服務器在啟動時讀入user表后進行排序。
l 然后當用戶試圖連接時,以排序的順序瀏覽條目
l 服務器使用與客戶端和用戶名匹配的第一行。
user表排序工作如下,假定user表看起來像這樣:
+-----------+----------+-
| Host | User | …
+-----------+----------+-
| % | root | …
| % | jeffrey | …
| localhost | root | …
| localhost | | …
+-----------+----------+-
當服務器讀取表時,它首先以最具體的Host值排序。主機名和IP號是最具體的。'%'意味著“任何主機”并且是最不特定的。有相同Host值的條目首先以最具體的User值排序(空User值意味著“任何用戶”并且是最不特定的)。最終排序的user表看起來像這樣:
+-----------+----------+-
| Host | User | …
+-----------+----------+-
| localhost | root | … ...
| localhost | | … ...
| % | jeffrey | … ...
| % | root | … ...
+-----------+----------+-
當客戶端試圖連接時,服務器瀏覽排序的條目并使用找到的第一匹配。對于由jeffrey從localhost的連接,表內有兩個條目匹配:Host和User值為'localhost'和''的條目,和值為'%'和'jeffrey'的條目。'localhost'條目首先匹配,服務器可以使用。
還有一個例子。假定user表看起來像這樣:
+----------------+----------+-
| Host | User | …
+----------------+----------+-
| % | jeffrey | …
| thomas.loc.gov | | …
+----------------+----------+-
排序后的表看起來像這樣:
+----------------+----------+-
| Host | User | …
+----------------+----------+-
| thomas.loc.gov | | …
| % | jeffrey | …
+----------------+----------+-
由jeffrey從thomas.loc.gov的連接與第一行匹配,而由jeffrey從whitehouse.gov的連接被第二個匹配。
普遍的誤解是認為,對給定的用戶名,當服務器試圖對連接尋找匹配時,明確命名那個用戶的所有條目將首先被使用。這明顯不符合事實。先前的例子說明了這點,在那里由jeffrey從thomas.loc.gov的連接沒被包含'jeffrey'作為User列值的行匹配,但是由沒有用戶名的題目匹配!結果是,jeffrey被鑒定為匿名用戶,即使他連接時指定了用戶名。
如果你能夠連接服務器,但你的權限不是你期望的,你可能被鑒定為其它賬戶。要想找出服務器用來鑒定你的賬戶,使用CURRENT_USER()函數。它返回user_name@host_name格式的值,說明User和Host 值匹配user表記錄。假定jeffrey連接并發出下面的查詢:
mysql> SELECT CURRENT_USER();
+----------------+
| CURRENT_USER() |
+----------------+
| @localhost |
+----------------+
這兒顯示的結果說明user表行有空的User列值。換句話說,服務器將jeffrey視為匿名用戶。
診斷鑒定問題的另一個方法是打印出user表并且手動排序它看看第一個匹配在哪兒進行。又見12.9.3節,“信息函數”。