1. 程式人生 > >MySQL Study之--MySQL普通使用者無法本地登陸

MySQL Study之--MySQL普通使用者無法本地登陸

一、登入後檢視mysql.user表的情況

可以看到,我的資料庫中有rose使用者和匿名使用者localhost;
mysql> show grants for rose;
+-----------------------------------------------------------------------------------------------------+
| Grants for [email protected]%                                                                                   |
+-----------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'rose'@'%' IDENTIFIED BY PASSWORD '*86F57026C60B8CE1038EFB3B9383EC573979A7BD' |
| GRANT ALL PRIVILEGES ON `prod`.* TO 'rose'@'%'                                                      |
+-----------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

二、在本機用rose使用者登入,發現不用密碼可以登入;

[[email protected] ~]# mysql -urose -p
Enter password: 

mysql> select user(),current_user();
+----------------+----------------+
| user()         | current_user() |
+----------------+----------------+
| [email protected] | @localhost     |
+----------------+----------------+
1 row in set (0.00 sec)

登入成功了,使用USER()和CURRENT_USER()兩個函式檢視所使用的使用者。

USER()函式返回你在客戶端登陸時指定的使用者名稱和主機名。
CURRENT_USER()函式返回的是MySQL使用授權表中的哪個使用者來認證你的登入請求。
這裡發現,我使用'rose'@'localhost'這個賬戶登入資料庫(因為在本地登陸時沒指定主機,預設是以localhost登入),但是資料庫使用的是''@'localhost'這個賬戶來進行登入認證,而''@'localhost'這個匿名使用者是沒有密碼的,因此我輸入空密碼登入成功了。但是登入後,所對應的使用者的匿名使用者。

一般在MySQL在安裝完畢後,我們使用mysql_install_db這個指令碼生成授權表,會預設建立''@'localhost'這個匿名使用者。正是因為這個匿名使用者,影響了其他使用者從本地登入的認證。

那麼MySQL是如何進行使用者身份認證呢?

        一、當用戶從客戶端請求登陸時,MySQL將授權表中的條目與客戶端所提供的條目進行比較,包括使用者的使用者名稱,密碼和主機。授權表中的Host欄位是可以使用萬用字元作為模式進行匹配的,如test.example.com, %.example.com, %.com和%都可以匹配test.example.com這個主機。授權表中的User欄位不允許使用模式匹配,但是可以有一個空字元的使用者名稱代表匿名使用者,並且空字串可以匹配所有的使用者名稱,就像萬用字元一樣。 當user表中的Host和User有多個值可以匹配客戶端提供的主機和使用者名稱時,MySQL將user表讀入記憶體,並且按照一定規則排序,按照排序規則讀取到的第一個匹配客戶端使用者名稱和主機名的條目對客戶端進行身份驗證。

       二、排序規則:對於Host欄位,按照匹配的精確程度進行排序,越精確的排序越前,例如當匹配test.example.com這個主機時, %.example.com比%.com更精確,而test.example.com比%.example.com更精確。對於User欄位,非空的字串使用者名稱比空字串匹配的使用者名稱排序更靠前。 User和Host欄位都有多個匹配值,MySQL使用主機名排序最前的條目,在主機名欄位相同時再選取使用者名稱排序更前的條目。因此,如果User和Host欄位都有多個匹配值,主機名最精確匹配的條目被使用者對使用者進行認證。

瞭解了這個認證流程,就知道為什麼server登入失敗了。
     使用GaMe在本機登入資料時,不指定-h引數預設為localhost主機登入,而在MySQL中有兩個匹配的條目:'rose'@'%'  和 ''@'localhost'
匿名使用者能夠匹配的原因上面說過,空字串可以匹配所有的使用者名稱,就像萬用字元一樣。
根據MySQL認證時的排序規則,第一個條目的使用者名稱排序更前,第二個條目的主機名更精確,排序更前。
而MySQL會優先使用主機名排序第一的條目進行身份認證,因此''@'localhost'被使用者對客戶端進行認證。因此,只有使用匿名使用者的空密碼才能登入進資料庫。就會出現下面的情況了。
    解決的方法:刪除匿名使用者(僅僅為了安全也有這個必要)
為什麼root使用者不會受影響,而只有普通使用者不能從本地登入?
因為mysql_install_db指令碼會在授權表中生成'root'@'localhost'這個賬戶。同樣的,使用root登入MySQL 時,'root'@'localhost'和''@'localhost'都能匹配登入的賬戶,但是根據排序規則,主機名相同,而使用者名稱非空字串優先,因此'root'@'localhost'這個條目的排序更靠前。使用root本地登入是不會被匿名使用者遮蓋。