兩階段權限驗證
- 連接驗證:客戶端發起連接 → 檢查
user 表:Host、User、authentication_string(密碼)、plugin(認證插件)。匹配成功 → 進入階段二。
- 操作授權:執行 SQL → 按層級檢查權限:Global → Database → Table → Column → Routine/Proxy。
權限表層級架構(mysql 系統庫)
| 表 | 層級 | 範圍 | 關鍵列 |
| user | 全局 | 整個服務器 | Select_priv, Insert_priv, ..., Super_priv, File_priv, Grant_priv |
| db | 庫級 | 特定數據庫 | Host, Db, User, Select_priv... |
| tables_priv | 表級 | 特定表 | Host, Db, User, Table_name, Table_priv, Column_priv |
| columns_priv | 列級 | 特定列 | Host, Db, User, Table_name, Column_name, Column_priv |
| procs_priv | 程序級 | 存儲過程/函數 | Host, Db, User, Routine_name, Routine_type, Proc_priv |
| proxies_priv | 代理級 | 代理用戶 | Host, User, Proxied_host, Proxied_user, Grantor, With_grant |
權限檢查邏輯(優先級遞減)
IF user_table グローバル権限 THEN ALLOW
ELSE IF db_table 库权限 THEN ALLOW
ELSE IF tables_priv 表权限 THEN ALLOW
ELSE IF columns_priv 列权限 THEN ALLOW
ELSE DENY
實戰授權模型
1. 開發人員(只讀+臨時表)
CREATE USER 'dev'@'%' IDENTIFIED BY 'dev_pass';
GRANT SELECT, CREATE TEMPORARY TABLES ON app_db.* TO 'dev'@'%';
2. 應用賬號(業務 CRUD,無 DDL)
CREATE USER 'app'@'10.0.%' IDENTIFIED BY 'strong_pass';
GRANT SELECT, INSERT, UPDATE, DELETE ON app_db.* TO 'app'@'10.0.%';
3. DBA 管理帳號(全權,僅內網)
CREATE USER 'dba'@'10.0.0.%' IDENTIFIED BY 'very_strong';
GRANT ALL PRIVILEGES ON *.* TO 'dba'@'10.0.0.%' WITH GRANT OPTION;
4. 只讀報表帳號(列級掩碼)
CREATE USER 'report'@'%' IDENTIFIED BY 'report_pass';
GRANT SELECT (id, name, status) ON app_db.users TO 'report'@'%'; -- 隱藏 phone/email
關鍵權限解析
| 權限 | 作用 | 風險等級 |
| FILE | LOAD DATA INFILE / SELECT INTO OUTFILE | 高(讀寫服務器文件) |
| SUPER | CHANGE MASTER, KILL, PURGE BINLOG, SET GLOBAL | 極高 |
| REPLICATION SLAVE | 從庫連接主庫 | 中 |
| GRANT OPTION | 授權給他人 | 高 |
| SHUTDOWN | 關閉服務器 | 極高 |
避坑指南
- 通配符主機 '%' 包含 localhost,**但不包含 127.0.0.1**(協議不同),需額外授權
'user'@'127.0.0.1'。
- 密碼插件:8.0 默認
caching_sha2_password,舊客戶端需 mysql_native_password。
- 權限緩存:
FLUSH PRIVILEGES 僅在直接修改權限表時需要,GRANT 語句自動生效。
- 匿名用戶:安裝後執行
mysql_secure_installation 或手動 DROP USER ''@'localhost'; DROP USER ''@'%';。