經典場景:建立帳號 'user'@'%' 遠程連線正常,但本機 mysql -u user -p 卻報 Access denied for user 'user'@'localhost',甚至免密登入卻無權限。 本文從 MySQL 認證排序規則切入,徹底解析「匿名用戶遮蔽」根因,提供兩種標準解法與驗證方法。
# Root 建立帳號 mysql> GRANT ALL ON prod.* TO 'rose'@'%' IDENTIFIED BY 'rose'; # 本地登入失敗 [root@mysrv ~]# mysql -u rose -prose ERROR 1045 (28000): Access denied for user 'rose'@'localhost' (using password: YES) # 免密登入卻進入(實際走匿名用戶) [root@mysrv ~]# mysql -u rose -p Enter password: # 直接 Enter Welcome to the MySQL monitor... mysql> USE prod; ERROR 1044 (42000): Access denied for user ''@'localhost' to database 'prod' # 遠程登入正常 C:\> mysql -h 192.168.8.240 -u rose -prose # 成功
MySQL 讀取 mysql.user 表到記憶體,依以下規則排序,取第一個匹配的行進行驗證:
'localhost' > '127.0.0.1' > '%'。'rose' > ''(匿名)。| Host | User | 匹配度說明 |
|---|---|---|
| localhost | '' (匿名) | Host 精確匹配,優先級最高 → 被選中 |
| % | rose | Host 通配,優先級較低 |
結果:本地連線實際使用 ''@'localhost' 驗證(無密碼),故免密可進,但無任何權限。
mysql_install_db 同時建立 'root'@'localhost'。本地登入時,'root'@'localhost' 與 ''@'localhost' Host 同精確度,但 User 非空優先,故 Root 走正確帳號驗證。
mysql> GRANT ALL ON prod.* TO 'rose'@'localhost' IDENTIFIED BY 'rose'; FLUSH PRIVILEGES;
新增 'rose'@'localhost' 後,Host 精確度並列,User 非空優先,本地登入即走正確帳號。
mysql> DROP USER ''@'localhost'; mysql> FLUSH PRIVILEGES;
移除遮蔽源頭,所有本地連線強制匹配具名帳號。
mysql> SELECT USER(), CURRENT_USER(); +----------------+----------------+ | USER() | CURRENT_USER() | +----------------+----------------+ | rose@localhost | rose@localhost | -- 解法生效後 +----------------+----------------+
USER():客戶端嘗試的帳號(含主機)CURRENT_USER():Server 實際用於驗證的帳號(權限表匹配行)兩者一致即表示無遮蔽問題。
'user'@'%' 與 'user'@'localhost'。DELETE FROM mysql.user WHERE User=''; FLUSH PRIVILEGES;mysql.user 確認無殘留匿名帳號。SELECT USER(), CURRENT_USER() 定位實際驗證帳號。理解「Host 精確度 > User 非空」的認證排序邏輯,是解決 MySQL 連線詭異問題的金鑰。