@[toc]
MySQL用戶管理
MySQL 是一個多用戶數(shù)據(jù)庫,具有功能強大的訪問控制系統(tǒng),可以為不同用戶指定不同權限。我們使用的是 root 用戶,該用戶是超級管理員,擁有所有權限,包括創(chuàng)建用戶、刪除用戶和修改用戶密碼等管理權限。
為了實際項目的需要,可以創(chuàng)建擁有不同權限的普通用戶。
MySQL user權限表詳解
MySQL 在安裝時會自動創(chuàng)建一個名為 mysql 的數(shù)據(jù)庫,mysql 數(shù)據(jù)庫中存儲的都是用戶權限表。用戶登錄以后,MySQL 會根據(jù)這些權限表的內(nèi)容為每個用戶賦予相應的權限。
user 表是 MySQL 中最重要的一個權限表,用來記錄允許連接到服務器的賬號信息。需要注意的是,在 user 表里啟用的所有權限都是全局級的,適用于所有數(shù)據(jù)庫。
user 表中的字段大致可以分為 4 類,分別是用戶列、權限列、安全列和資源控制列,下面主要介紹這些字段的含義。
用戶列
用戶列存儲了用戶連接 MySQL 數(shù)據(jù)庫時需要輸入的信息。需要注意的是 MySQL 5.7 版本不再使用 Password 來作為密碼的字段,而改成了 authentication_string。
MySQL 5.7 版本的用戶列如表所示。
| 字段名 | 字段類型 | 是否為空 | 默認值 | 說明 |
|---|---|---|---|---|
| Host | char(60) | NO | 無 | 主機名 |
| User | char(32) | NO | 無 | 用戶名 |
| authentication_string | text | YES | 無 | 密碼 |
用戶登錄時,如果這 3 個字段同時匹配,MySQL 數(shù)據(jù)庫系統(tǒng)才會允許其登錄。創(chuàng)建新用戶時,也是設置這 3 個字段的值。修改用戶密碼時,實際就是修改 user 表的 authentication_string 字段的值。因此,這 3 個字段決定了用戶能否登錄。
權限列
權限列的字段決定了用戶的權限,用來描述在全局范圍內(nèi)允許對數(shù)據(jù)和數(shù)據(jù)庫進行的操作。
權限大致分為兩大類,分別是高級管理權限和普通權限:
- 高級管理權限主要對數(shù)據(jù)庫進行管理,例如關閉服務的權限、超級權限和加載用戶等;
- 普通權限主要操作數(shù)據(jù)庫,例如查詢權限、修改權限等。
user 表的權限列包括 Select_priv、Insert_ priv 等以 priv 結尾的字段,這些字段值的數(shù)據(jù)類型為 ENUM,可取的值只有 Y 和 N:Y 表示該用戶有對應的權限,N 表示該用戶沒有對應的權限。從安全角度考慮,這些字段的默認值都為 N。
| 字段名 | 字段類型 | 是否為空 | 默認值 | 說明 |
|---|---|---|---|---|
| Select_priv | enum('N','Y') | NO | N | 是否可以通過SELECT 命令查詢數(shù)據(jù) |
| Insert_priv | enum('N','Y') | NO | N | 是否可以通過 INSERT 命令插入數(shù)據(jù) |
| Update_priv | enum('N','Y') | NO | N | 是否可以通過UPDATE 命令修改現(xiàn)有數(shù)據(jù) |
| Delete_priv | enum('N','Y') | NO | N | 是否可以通過DELETE 命令刪除現(xiàn)有數(shù)據(jù) |
| Create_priv | enum('N','Y') | NO | N | 是否可以創(chuàng)建新的數(shù)據(jù)庫和表 |
| Drop_priv | enum('N','Y') | NO | N | 是否可以刪除現(xiàn)有數(shù)據(jù)庫和表 |
| Reload_priv | enum('N','Y') | NO | N | 是否可以執(zhí)行刷新和重新加載MySQL所用的各種內(nèi)部緩存的特定命令,包括日志、權限、主機、查詢和表 |
| Shutdown_priv | enum('N','Y') | NO | N | 是否可以關閉MySQL服務器。將此權限提供給root賬戶之外的任何用戶時,都應當非常謹慎 |
| Process_priv | enum('N','Y') | NO | N | 是否可以通過SHOW PROCESSLIST命令查看其他用戶的進程 |
| File_priv | enum('N','Y') | NO | N | 是否可以執(zhí)行SELECT INTO OUTFILE和LOAD DATA INFILE命令 |
| Grant_priv | enum('N','Y') | NO | N | 是否可以將自己的權限再授予其他用戶 |
| References_priv | enum('N','Y') | NO | N | 是否可以創(chuàng)建外鍵約束 |
| Index_priv | enum('N','Y') | NO | N | 是否可以對索引進行增刪查 |
| Alter_priv | enum('N','Y') | NO | N | 是否可以重命名和修改表結構 |
| Show_db_priv | enum('N','Y') | NO | N | 是否可以查看服務器上所有數(shù)據(jù)庫的名字,包括用戶擁有足夠訪問權限的數(shù)據(jù)庫 |
| Super_priv | enum('N','Y') | NO | N | 是否可以執(zhí)行某些強大的管理功能,例如通過KILL命令刪除用戶進程;使用SET GLOBAL命令修改全局MySQL變量,執(zhí)行關于復制和日志的各種命令。(超級權限) |
| Create_tmp_table_priv | enum('N','Y') | NO | N | 是否可以創(chuàng)建臨時表 |
| Lock_tables_priv | enum('N','Y') | NO | N | 是否可以使用LOCK TABLES命令阻止對表的訪問/修改 |
| Execute_priv | enum('N','Y') | NO | N | 是否可以執(zhí)行存儲過程 |
| Repl_slave_priv | enum('N','Y') | NO | N | 是否可以讀取用于維護復制數(shù)據(jù)庫環(huán)境的二進制日志文件 |
| Repl_client_priv | enum('N','Y') | NO | N | 是否可以確定復制從服務器和主服務器的位置 |
| Create_view_priv | enum('N','Y') | NO | N | 是否可以創(chuàng)建視圖 |
| Show_view_priv | enum('N','Y') | NO | N | 是否可以查看視圖 |
| Create_routine_priv | enum('N','Y') | NO | N | 是否可以更改或放棄存儲過程和函數(shù) |
| Alter_routine_priv | enum('N','Y') | NO | N | 是否可以修改或刪除存儲函數(shù)及函數(shù) |
| Create_user_priv | enum('N','Y') | NO | N | 是否可以執(zhí)行CREATE USER命令,這個命令用于創(chuàng)建新的MySQL賬戶 |
| Event_priv | enum('N','Y') | NO | N | 是否可以創(chuàng)建、修改和刪除事件 |
| Trigger_priv | enum('N','Y') | NO | N | 是否可以創(chuàng)建和刪除觸發(fā)器 |
| Create_tablespace_priv | enum('N','Y') | NO | N | 是否可以創(chuàng)建表空間 |
如果要修改權限,可以使用 GRANT 語句為用戶賦予一些權限,也可以通過 UPDATE 語句更新 user 表的方式來設置權限。
安全列
安全列主要用來判斷用戶是否能夠登錄成功,user 表中的安全列如表所示:
| 字段名 | 字段類型 | 是否為空 | 默認值 | 說明 |
|---|---|---|---|---|
| ssl_type | enum('','ANY','X509','SPECIFIED') | NO | 支持ssl標準加密安全字段 | |
| ssl_cipher | blob | NO | 支持ssl標準加密安全字段 | |
| x509_issuer | blob | NO | 支持x509標準字段 | |
| x509_subject | blob | NO | 支持x509標準字段 | |
| plugin | char(64) | NO | mysql_native_password | 引入plugins以進行用戶連接時的密碼驗證,plugin創(chuàng)建外部/代理用戶 |
| password_expired | enum('N','Y') | NO | N | 密碼是否過期 (N 未過期,y 已過期) |
| password_last_changed | timestamp | YES | 記錄密碼最近修改的時間 | |
| password_lifetime | smallint(5) unsigned | YES | 設置密碼的有效時間,單位為天數(shù) | |
| account_locked | enum('N','Y') | NO | N | 用戶是否被鎖定(Y 鎖定,N 未鎖定) |
注意:即使 password_expired 為“Y”,用戶也可以使用密碼登錄 MySQL,但是不允許做任何操作。
通常標準的發(fā)行版不支持 ssl,讀者可以使用 SHOW VARIABLES LIKE "have_openssl" 語句來查看是否具有 ssl 功能。如果 have_openssl 的值為 DISABLED,那么則不支持 ssl 加密功能。
資源控制列
資源控制列的字段用來限制用戶使用的資源,user 表中的資源控制列如表 4 所示。
| 字段名 | 字段類型 | 是否為空 | 默認值 | 說明 |
|---|---|---|---|---|
| max_questions | int(11) unsigned | NO | 0 | 規(guī)定每小時允許執(zhí)行查詢的操作次數(shù) |
| max_updates | int(11) unsigned | NO | 0 | 規(guī)定每小時允許執(zhí)行更新的操作次數(shù) |
| max_connections | int(11) unsigned | NO | 0 | 規(guī)定每小時允許執(zhí)行的連接操作次數(shù) |
| max_user_connections | int(11) unsigned | NO | 0 | 規(guī)定允許同時建立的連接次數(shù) |
以上字段的默認值為 0,表示沒有限制。一個小時內(nèi)用戶查詢或者連接數(shù)量超過資源控制限制,用戶將被鎖定,直到下一個小時才可以在此執(zhí)行對應的操作??梢允褂?GRANT 語句更新這些字段的值。
MySQL 其他權限表
在 MySQL 數(shù)據(jù)庫中,權限表除了 user 表外,還有 db 表、tables_priv 表、columns_priv 表和 procs_priv 表。
db表
db 表比較常用,是 MySQL 數(shù)據(jù)庫中非常重要的權限表,表中存儲了用戶對某個數(shù)據(jù)庫的操作權限。表中的字段大致可以分為兩類,分別是用戶列和權限列。
用戶列
db 表用戶列有 3 個字段,分別是 Host、User、Db,標識從某個主機連接某個用戶對某個數(shù)據(jù)庫的操作權限,這 3 個字段的組合構成了 db 表的主鍵。
db 表的用戶列如下表所示:
| 字段名 | 字段類型 | 是否為空 | 默認值 | 說明 |
|---|---|---|---|---|
| Host | char(60) | NO | 無 | 主機名 |
| Db | char(64) | NO | 無 | 數(shù)據(jù)庫名 |
| User | char(32) | NO | 無 | 用戶名 |
權限列
db 表中的權限列和 user 表中的權限列大致相同,只是user 表中的權限是針對所有數(shù)據(jù)庫的,而 db 表中的權限只針對指定的數(shù)據(jù)庫。如果希望用戶只對某個數(shù)據(jù)庫有操作權限,可以先將 user 表中對應的權限設置為 N,然后在 db 表中設置對應數(shù)據(jù)庫的操作權限。
tables_priv表和columns_priv表
tables_priv 表用來對單個表進行權限設置,columns_priv 表用來對單個數(shù)據(jù)列進行權限設置。tables_priv 表結構如下表所示:
| 字段名 | 字段類型 | 是否為空 | 默認值 | 說明 |
|---|---|---|---|---|
| Host | char(60) | NO | 無 | 主機 |
| Db | char(64) | NO | 無 | 數(shù)據(jù)庫名 |
| User | char(32) | NO | 無 | 用戶名 |
| Table_name | char(64) | NO | 無 | 表名 |
| Grantor | char(93) | NO | 無 | 修改該記錄的用戶 |
| Timestamp | timestamp | NO | CURRENT_TIMESTAMP | 修改該記錄的時間 |
| Table_priv | set() | NO | 無 | 表示對表的操作權限,包括 Select、Insert、Update、Delete、Create、Drop、Grant、References、Index 和 Alter 等 |
| Column_priv | set('Select','Insert','Update','References') | NO | 無 | 表示對表中的列的操作權限,包括 Select、Insert、Update 和 References |
columns_priv 表結構如下表所示:
| 字段名 | 字段類型 | 是否為空 | 默認值 | 說明 |
|---|---|---|---|---|
| Host | char(60) | NO | 無 | 主機 |
| Db | char(64) | NO | 無 | 數(shù)據(jù)庫名 |
| User | char(32) | NO | 無 | 用戶名 |
| Table_name | char(64) | NO | 無 | 表名 |
| Column_name | char(64) | NO | 無 | 數(shù)據(jù)列名稱,用來指定對哪些數(shù)據(jù)列具有操作權限 |
| Timestamp | timestamp | NO | CURRENT_TIMESTAMP | 修改該記錄的時間 |
| Column_priv | set('Select','Insert','Update','References') | NO | 無 | 表示對表中的列的操作權限,包括 Select、Insert、Update 和 References |
procs_priv表
procs_priv 表可以對存儲過程和存儲函數(shù)進行權限設置,procs_priv 的表結構如表所示:
| 字段名 | 字段類型 | 是否為空 | 默認值 | 說明 |
|---|---|---|---|---|
| Host | char(60) | NO | 無 | 主機名 |
| Db | char(64) | NO | 無 | 數(shù)據(jù)庫名 |
| User | char(32) | NO | 無 | 用戶名 |
| Routine_name | char(64) | NO | 無 | 表示存儲過程或函數(shù)的名稱 |
| Routine_type | enum('FUNCTION','PROCEDURE') | NO | 無 | 表示存儲過程或函數(shù)的類型,Routine_type 字段有兩個值,分別是 FUNCTION 和 PROCEDURE。FUNCTION 表示這是一個函數(shù);PROCEDURE 表示這是一個 存儲過程。 |
| Grantor | char(93) | NO | 無 | 插入或修改該記錄的用戶 |
| Proc_priv | set('Execute','Alter Routine','Grant') | NO | 無 | 表示擁有的權限,包括 Execute、Alter Routine、Grant 3種 |
| Timestamp | timestamp | NO | CURRENT_TIMESTAMP | 表示記錄更新時間 |
MySQL創(chuàng)建用戶
MySQL 在安裝時,會默認創(chuàng)建一個名為 root 的用戶,該用戶擁有超級權限,可以控制整個 MySQL 服務器。
在對 MySQL 的日常管理和操作中,為了避免有人惡意使用 root 用戶控制數(shù)據(jù)庫,我們通常創(chuàng)建一些具有適當權限的用戶,盡可能地不用或少用 root 用戶登錄系統(tǒng),以此來確保數(shù)據(jù)的安全訪問。
MySQL 提供了以下 3 種方法創(chuàng)建用戶。
- 使用 CREATE USER 語句創(chuàng)建用戶
- 在 mysql.user 表中添加用戶
- 使用 GRANT 語句創(chuàng)建用戶
使用CREATE USER語句創(chuàng)建用戶
可以使用 CREATE USER 語句來創(chuàng)建 MySQL 用戶,并設置相應的密碼。其基本語法格式如下:
CREATE USER <用戶> [ IDENTIFIED BY [ PASSWORD ] 'password' ] [ ,用戶 [ IDENTIFIED BY [ PASSWORD ] 'password' ]]
參數(shù)說明如下:
- 用戶:指定創(chuàng)建用戶賬號,格式為
user_name'@'host_name。這里的user_name是用戶名,host_name為主機名,即用戶連接 MySQL 時所用主機的名字。如果在創(chuàng)建的過程中,只給出了用戶名,而沒指定主機名,那么主機名默認為“%”,表示一組主機,即對所有主機開放權限。 - IDENTIFIED BY子句:用于指定用戶密碼。新用戶可以沒有初始密碼,若該用戶不設密碼,可省略此子句。
- PASSWORD 'password':PASSWORD 表示使用哈希值設置密碼,該參數(shù)可選。如果密碼是一個普通的字符串,則不需要使用 PASSWORD 關鍵字。'password' 表示用戶登錄時使用的密碼,需要用單引號括起來。
使用 CREATE USER 語句時應注意以下幾點:
- CREATE USER 語句可以不指定初始密碼。但是從安全的角度來說,不推薦這種做法。
- 使用 CREATE USER 語句必須擁有 mysql 數(shù)據(jù)庫的 INSERT 權限或全局 CREATE USER 權限。
- 使用 CREATE USER 語句創(chuàng)建一個用戶后,MySQL 會在 mysql 數(shù)據(jù)庫的 user 表中添加一條新記錄。
- CREATE USER 語句可以同時創(chuàng)建多個用戶,多個用戶用逗號隔開。
新創(chuàng)建的用戶擁有的權限很少,它們只能執(zhí)行不需要權限的操作。如登錄 MySQL、使用 SHOW 語句查詢所有存儲引擎和字符集的列表等。如果兩個用戶的用戶名相同,但主機名不同,MySQL 會將它們視為兩個用戶,并允許為這兩個用戶分配不同的權限集合。
使用 INSERT 語句新建用戶
可以使用 INSERT 語句將用戶的信息添加到 mysql.user 表中,但必須擁有對 mysql.user 表的 INSERT 權限。通常 INSERT 語句只添加 Host、User 和 authentication_string 這 3 個字段的值。
使用 INSERT 語句創(chuàng)建用戶的代碼如下:
INSERT INTO mysql.user(Host, User, authentication_string, ssl_cipher, x509_issuer, x509_subject) VALUES ('hostname', 'username', PASSWORD('password'), '', '', '');
由于 mysql 數(shù)據(jù)庫的 user 表中,ssl_cipher、x509_issuer 和 x509_subject 這 3 個字段沒有默認值,所以向 user 表插入新記錄時,一定要設置這 3 個字段的值,否則 INSERT 語句將不能執(zhí)行。
下面使用 INSERT 語句創(chuàng)建名為 test2 的用戶,主機名是 localhost,密碼也是 test2。SQL 語句和執(zhí)行過程如下:
mysql> INSERT INTO mysql.user(Host, User, authentication_string, ssl_cipher, x509_issuer, x509_subject) VALUES ('localhost', 'test2', PASSWORD('test2'), '', '', '');
Query OK, 1 row affected, 1 warning (0.02 sec)
結果顯示,新建用戶成功。但是這時如果通過該賬戶登錄 MySQL 服務器,不會登錄成功,因為 test2 用戶還沒有生效。
可以使用 FLUSH 命令讓用戶生效,命令如下:
FLUSH PRIVILEGES;
使用以上命令可以讓 MySQL 刷新系統(tǒng)權限相關表。執(zhí)行 FLUSH 命令需要 RELOAD 權限。
注意:user 表中的 User 和 Host 字段區(qū)分大小寫,創(chuàng)建用戶時要指定正確的用戶名稱或主機名。
使用GRANT語句新建用戶
雖然 CREATE USER 和 INSERT INTO 語句都可以創(chuàng)建普通用戶,但是這兩種方式不便授予用戶權限。于是 MySQL 提供了 GRANT 語句。
使用 GRANT 語句創(chuàng)建用戶的基本語法形式如下:
GRANT priv_type ON database.table TO user [IDENTIFIED BY [PASSWORD] 'password']
其中:
- priv_type 參數(shù)表示新用戶的權限;
- database.table 參數(shù)表示新用戶的權限范圍,即只能在指定的數(shù)據(jù)庫和表上使用自己的權限;
- user 參數(shù)指定新用戶的賬號,由用戶名和主機名構成;
- IDENTIFIED BY 關鍵字用來設置密碼;
- password 參數(shù)表示新用戶的密碼。
技巧:GRANT 語句是 MySQL 中一個非常重要的語句,它可以用來創(chuàng)建用戶、修改用戶密碼和設置用戶權限。教程后面會詳細介紹如何使用 GRANT 語句修改密碼、更改權限。
MySQL修改用戶
在 MySQL 中,我們可以使用 RENAME USER 語句修改一個或多個已經(jīng)存在的用戶賬號。
語法格式如下:
RENAME USER <舊用戶> TO <新用戶>
其中:
- <舊用戶>:系統(tǒng)中已經(jīng)存在的 MySQL 用戶賬號。
- <新用戶>:新的 MySQL 用戶賬號。
使用 RENAME USER 語句時應注意以下幾點:
- RENAME USER 語句用于對原有的 MySQL 用戶進行重命名。
- 若系統(tǒng)中舊賬戶不存在或者新賬戶已存在,該語句執(zhí)行時會出現(xiàn)錯誤。
- 使用 RENAME USER 語句,必須擁有 mysql 數(shù)據(jù)庫的 UPDATE 權限或全局 CREATE USER 權限。
MySQL刪除用戶
在 MySQL 數(shù)據(jù)庫中,可以使用 DROP USER 語句刪除用戶,也可以直接在 mysql.user 表中刪除用戶以及相關權限。
使用 DROP USER 語句刪除普通用戶
使用 DROP USER 語句刪除用戶的語法格式如下:
DROP USER <用戶1> [ , <用戶2> ]…
其中,用戶用來指定需要刪除的用戶賬號。
使用 DROP USER 語句應注意以下幾點:
- DROP USER 語句可用于刪除一個或多個用戶,并撤銷其權限。
- 使用 DROP USER 語句必須擁有 mysql 數(shù)據(jù)庫的 DELETE 權限或全局 CREATE USER 權限。
- 在 DROP USER 語句的使用中,若沒有明確地給出賬戶的主機名,則該主機名默認為“%”。
注意:用戶的刪除不會影響他們之前所創(chuàng)建的表、索引或其他數(shù)據(jù)庫對象,因為 MySQL 并不會記錄是誰創(chuàng)建了這些對象。
使用DELETE語句刪除普通用戶
可以使用 DELETE 語句直接刪除 mysql.user 表中相應的用戶信息,但必須擁有 mysql.user 表的 DELETE 權限。其基本語法格式如下:
DELETE FROM mysql.user WHERE Host='hostname' AND User='username';
Host 和 User 這兩個字段都是 mysql.user 表的主鍵。因此,需要兩個字段的值才能確定一條記錄。
MySQL查看用戶權限
在 MySQL 中,可以通過查看 mysql.user 表中的數(shù)據(jù)記錄來查看相應的用戶權限,也可以使用 SHOW GRANTS 語句查詢用戶的權限。
mysql 數(shù)據(jù)庫下的 user 表中存儲著用戶的基本權限,可以使用 SELECT 語句來查看。SELECT 語句的代碼如下:
SELECT * FROM mysql.user;
要執(zhí)行該語句,必須擁有對 user 表的查詢權限。
注意:新創(chuàng)建的用戶只有登錄 MySQL 服務器的權限,沒有任何其它權限,不能查詢 user 表。
除了使用 SELECT 語句之外,還可以使用 SHOW GRANTS FOR 語句查看權限。其語法格式如下:
SHOW GRANTS FOR 'username'@'hostname';
其中,username 表示用戶名,hostname 表示主機名或主機 IP。
MySQL 用戶授權
授權就是為某個用戶賦予某些權限。例如,可以為新建的用戶賦予查詢所有數(shù)據(jù)庫和表的權限。MySQL 提供了 GRANT 語句來為用戶設置權限。
在 MySQL 中,擁有 GRANT 權限的用戶才可以執(zhí)行 GRANT 語句,其語法格式如下:
GRANT priv_type [(column_list)] ON database.table
TO user [IDENTIFIED BY [PASSWORD] 'password']
[, user[IDENTIFIED BY [PASSWORD] 'password']] ...
[WITH with_option [with_option]...]
其中:
- priv_type 參數(shù)表示權限類型;
- columns_list 參數(shù)表示權限作用于哪些列上,省略該參數(shù)時,表示作用于整個表;
- database.table 用于指定權限的級別;
- user 參數(shù)表示用戶賬戶,由用戶名和主機名構成,格式是“'username'@'hostname'”;
- IDENTIFIED BY 參數(shù)用來為用戶設置密碼;
- password 參數(shù)是用戶的新密碼。
WITH 關鍵字后面帶有一個或多個 with_option 參數(shù)。這個參數(shù)有 5 個選項,詳細介紹如下:
- GRANT OPTION:被授權的用戶可以將這些權限賦予給別的用戶;
- MAX_QUERIES_PER_HOUR count:設置每個小時可以允許執(zhí)行 count 次查詢;
- MAX_UPDATES_PER_HOUR count:設置每個小時可以允許執(zhí)行 count 次更新;
- MAX_CONNECTIONS_PER_HOUR count:設置每小時可以建立 count 個連接;
- MAX_USER_CONNECTIONS count:設置單個用戶可以同時具有的 count 個連接。
MySQL 中可以授予的權限有如下幾組:
- 列權限,和表中的一個具體列相關。例如,可以使用 UPDATE 語句更新表 students 中 name 列的值的權限。
- 表權限,和一個具體表中的所有數(shù)據(jù)相關。例如,可以使用 SELECT 語句查詢表 students 的所有數(shù)據(jù)的權限。
- 數(shù)據(jù)庫權限,和一個具體的數(shù)據(jù)庫中的所有表相關。例如,可以在已有的數(shù)據(jù)庫 mytest 中創(chuàng)建新表的權限。
- 用戶權限,和 MySQL 中所有的數(shù)據(jù)庫相關。例如,可以刪除已有的數(shù)據(jù)庫或者創(chuàng)建一個新的數(shù)據(jù)庫的權限。
對應地,在 GRANT 語句中可用于指定權限級別的值有以下幾類格式:
- *:表示當前數(shù)據(jù)庫中的所有表。
- .:表示所有數(shù)據(jù)庫中的所有表。
- db_name.*:表示某個數(shù)據(jù)庫中的所有表,db_name 指定數(shù)據(jù)庫名。
- db_name.tbl_name:表示某個數(shù)據(jù)庫中的某個表或視圖,db_name 指定數(shù)據(jù)庫名,tbl_name 指定表名或視圖名。
- db_name.routine_name:表示某個數(shù)據(jù)庫中的某個存儲過程或函數(shù),routine_name 指定存儲過程名或函數(shù)名。
- TO 子句:如果權限被授予給一個不存在的用戶,MySQL 會自動執(zhí)行一條 CREATE USER 語句來創(chuàng)建這個用戶,但同時必須為該用戶設置密碼。
權限類型說明
授予數(shù)據(jù)庫權限時,<權限類型>可以指定為以下值:
| 權限名稱 | 對應user表中的字段 | 說明 |
|---|---|---|
| SELECT | Select_priv | 表示授予用戶可以使用 SELECT 語句訪問特定數(shù)據(jù)庫中所有表和視圖的權限。 |
| INSERT | Insert_priv | 表示授予用戶可以使用 INSERT 語句向特定數(shù)據(jù)庫中所有表添加數(shù)據(jù)行的權限。 |
| DELETE | Delete_priv | 表示授予用戶可以使用 DELETE 語句刪除特定數(shù)據(jù)庫中所有表的數(shù)據(jù)行的權限。 |
| UPDATE | Update_priv | 表示授予用戶可以使用 UPDATE 語句更新特定數(shù)據(jù)庫中所有數(shù)據(jù)表的值的權限。 |
| REFERENCES | References_priv | 表示授予用戶可以創(chuàng)建指向特定的數(shù)據(jù)庫中的表外鍵的權限。 |
| CREATE | Create_priv | 表示授權用戶可以使用 CREATE TABLE 語句在特定數(shù)據(jù)庫中創(chuàng)建新表的權限。 |
| ALTER | Alter_priv | 表示授予用戶可以使用 ALTER TABLE 語句修改特定數(shù)據(jù)庫中所有數(shù)據(jù)表的權限。 |
| SHOW VIEW | Show_view_priv | 表示授予用戶可以查看特定數(shù)據(jù)庫中已有視圖的視圖定義的權限。 |
| CREATE ROUTINE | Create_routine_priv | 表示授予用戶可以為特定的數(shù)據(jù)庫創(chuàng)建存儲過程和存儲函數(shù)的權限。 |
| ALTER ROUTINE | Alter_routine_priv | 表示授予用戶可以更新和刪除數(shù)據(jù)庫中已有的存儲過程和存儲函數(shù)的權限。 |
| INDEX | Index_priv | 表示授予用戶可以在特定數(shù)據(jù)庫中的所有數(shù)據(jù)表上定義和刪除索引的權限。 |
| DROP | Drop_priv | 表示授予用戶可以刪除特定數(shù)據(jù)庫中所有表和視圖的權限。 |
| CREATE TEMPORARY TABLES | Create_tmp_table_priv | 表示授予用戶可以在特定數(shù)據(jù)庫中創(chuàng)建臨時表的權限。 |
| CREATE VIEW | Create_view_priv | 表示授予用戶可以在特定數(shù)據(jù)庫中創(chuàng)建新的視圖的權限。 |
| EXECUTE ROUTINE | Execute_priv | 表示授予用戶可以調(diào)用特定數(shù)據(jù)庫的存儲過程和存儲函數(shù)的權限。 |
| LOCK TABLES | Lock_tables_priv | 表示授予用戶可以鎖定特定數(shù)據(jù)庫的已有數(shù)據(jù)表的權限。 |
| ALL 或 ALL PRIVILEGES 或 SUPER | Super_priv | 表示以上所有權限/超級權限 |
授予表權限時,<權限類型>可以指定為以下值:
| 權限名稱 | 對應user表中的字段 | 說明 |
|---|---|---|
| SELECT | Select_priv | 授予用戶可以使用 SELECT 語句進行訪問特定表的權限 |
| INSERT | Insert_priv | 授予用戶可以使用 INSERT 語句向一個特定表中添加數(shù)據(jù)行的權限 |
| DELETE | Delete_priv | 授予用戶可以使用 DELETE 語句從一個特定表中刪除數(shù)據(jù)行的權限 |
| DROP | Drop_priv | 授予用戶可以刪除數(shù)據(jù)表的權限 |
| UPDATE | Update_priv | 授予用戶可以使用 UPDATE 語句更新特定數(shù)據(jù)表的權限 |
| ALTER | Alter_priv | 授予用戶可以使用 ALTER TABLE 語句修改數(shù)據(jù)表的權限 |
| REFERENCES | References_priv | 授予用戶可以創(chuàng)建一個外鍵來參照特定數(shù)據(jù)表的權限 |
| CREATE | Create_priv | 授予用戶可以使用特定的名字創(chuàng)建一個數(shù)據(jù)表的權限 |
| INDEX | Index_priv | 授予用戶可以在表上定義索引的權限 |
| ALL 或 ALL PRIVILEGES 或 SUPER | Super_priv | 所有的權限名 |
授予列權限時,<權限類型>的值只能指定為 SELECT、INSERT 和 UPDATE,同時權限的后面需要加上列名列表 column-list。
最有效率的權限是用戶權限。
授予用戶權限時,<權限類型>除了可以指定為授予數(shù)據(jù)庫權限時的所有值之外,還可以是下面這些值:
- CREATE USER:表示授予用戶可以創(chuàng)建和刪除新用戶的權限。
- SHOW DATABASES:表示授予用戶可以使用 SHOW DATABASES 語句查看所有已有的數(shù)據(jù)庫的定義的權限。
數(shù)據(jù)庫管理員給普通用戶授權時一定要特別小心,如果授權不當,可能會給數(shù)據(jù)庫帶來致命的破壞。一旦發(fā)現(xiàn)給用戶的權限太多,應該盡快使用 REVOKE 語句將權限收回。此處特別注意,最好不要授予普通用戶 SUPER 權限,GRANT 權限。
MySQL 刪除用戶權限
在 MySQL 中,可以使用 REVOKE 語句刪除某個用戶的某些權限(此用戶不會被刪除),在一定程度上可以保證系統(tǒng)的安全性。
- 例如,如果數(shù)據(jù)庫管理員覺得某個用戶不應該擁有 DELETE 權限,那么就可以刪除 DELETE 權限。
使用 REVOKE 語句刪除權限的語法格式有兩種形式,如下所示:
刪除用戶某些特定的權限,語法格式如下:
REVOKE priv_type [(column_list)]...
ON database.table
FROM user [, user]...
REVOKE 語句中的參數(shù)與 GRANT 語句的參數(shù)意思相同。其中:
- priv_type 參數(shù)表示權限的類型;
- column_list 參數(shù)表示權限作用于哪些列上,沒有該參數(shù)時作用于整個表上;
- user 參數(shù)由用戶名和主機名構成,格式為“username'@'hostname'”。
刪除特定用戶的所有權限,語法格式如下:
REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...
刪除用戶權限需要注意以下幾點:
- REVOKE 語法和 GRANT 語句的語法格式相似,但具有相反的效果。
- 要使用 REVOKE 語句,必須擁有 MySQL 數(shù)據(jù)庫的全局 CREATE USER 權限或 UPDATE 權限。
MySQL登錄和退出服務器
啟動 MySQL 服務后,可以使用以下命令來登錄。
mysql -h hostname|hostlP -p port -u username -p DatabaseName -e "SQL語句"
對上述參數(shù)說明如下:
- -h:指定連接 MySQL 服務器的地址??梢杂脙煞N方式表示,hostname 為主機名,hostIP 為主機 IP 地址。
- -p:指定連接 MySQL 服務器的端口號,port 為連接的端口號。MySQL 的默認端口號是 3306,因此如果不指定該參數(shù),默認使用 3306 連接 MySQL 服務器。
- -u:指定連接 MySQL 服務器的用戶名,username 為用戶名。
- -p:提示輸入密碼,即提示 Enter password。
- DatabaseName:指定連接到 MySQL 服務器后,登錄到哪一個數(shù)據(jù)庫中。如果沒有指定,默認為 mysql 數(shù)據(jù)庫。
- -e:指定需要執(zhí)行的 SQL 語句,登錄 MySQL 服務器后執(zhí)行這個 SQL 語句,然后退出 MySQL 服務器。
退出 MySQL 服務器的方式很簡單,只要在命令行輸入 EXIT 或 QUIT 即可?!癨q”是 QUIT 的縮寫,也可以用來退出 MySQL 服務器。退出后就會顯示 Bye。如下:
mysql> QUIT;
Bye
MySQL root修改普通用戶密碼
在 MySQL 中,root 用戶擁有很高的權限,不僅可以修改自己的密碼,還可以修改其他用戶的密碼
使用SET語句修改普通用戶的密碼
在 MySQL 中,只有 root 用戶可以通過更新 MySQL 數(shù)據(jù)庫來更改密碼。使用 root 用戶登錄到 MySQL 服務器后,可以使用 SET 語句來修改普通用戶密碼。語法格式如下:
SET PASSWORD FOR 'username'@'hostname' = PASSWORD ('newpwd');
其中,username 參數(shù)是普通用戶的用戶名,hostname 參數(shù)是普通用戶的主機名,newpwd 是要更改的新密碼。
注意:新密碼必須使用 PASSWORD() 函數(shù)來加密,如果不使用 PASSWORD() 加密,也會執(zhí)行成功,但是用戶會無法登錄。
如果是普通用戶修改密碼,可省略 FOR 子句來更改自己的密碼。語法格式如下:
SET PASSWORD = PASSWORD('newpwd');
使用UPDATE語句修改普通用戶的密碼
使用 root 用戶登錄 MySQL 服務器后,可以使用 UPDATE 語句修改 MySQL 數(shù)據(jù)庫的 user 表的 authentication_string 字段,從而修改普通用戶的密碼。UPDATA 語句的語法如下:
UPDATE MySQL.user SET authentication_string = PASSWORD("newpwd") WHERE User = "username" AND Host = "hostname";
其中,username 參數(shù)是普通用戶的用戶名,hostname 參數(shù)是普通用戶的主機名,newpwd 是要更改的新密碼。
注意,執(zhí)行 UPDATE 語句后,需要執(zhí)行 FLUSH PRIVILEGES 語句重新加載用戶權限。
使用 GRANT 語句修改普通用戶密碼
還可以在全局級別使用 GRANT USAGE 語句指定某個賬戶的密碼而不影響賬戶當前的權限。需要注意的是,使用 GRANT 語句修改密碼,必須擁有 GRANT 權限。一般情況下最好使用該方法來指定或修改密碼。語法格式如下:
GRANT USAGE ON *.* TO 'user'@’hostname’ IDENTIFIED BY 'newpwd';
其中,username 參數(shù)是普通用戶的用戶名,hostname 參數(shù)是普通用戶的主機名,newpwd 是要更改的新密碼。
MySQL修改root密碼
在 MySQL 中,root 用戶擁有很高的權限,因此必須保證 root 用戶密碼的安全。修改 root 用戶密碼的方式有很多種,
使用mysqladmin命令在命令行指定新密碼
root 用戶可以使用 mysqladmin 命令來修改密碼,mysqladmin 的語法格式如下:
mysqladmin -u username -h hostname -p password "newpwd"
語法參數(shù)說明如下:
- usermame 指需要修改密碼的用戶名稱,在這里指定為 root 用戶;
- hostname 指需要修改密碼的用戶主機名,該參數(shù)可以不寫,默認是 localhost;
- password 為關鍵字,而不是指舊密碼;
- newpwd 為新設置的密碼,必須用雙引號括起來。如果使用單引號會引發(fā)錯誤,可能會造成修改后的密碼不是你想要的。
執(zhí)行完上面的語句,root 用戶的密碼將被修改為“newpwd”。
修改MySQL數(shù)據(jù)庫的user表
因為所有賬戶信息都保存在 user 表中,因此可以直接通過修改 user 表來改變 root 用戶的密碼。
root 用戶登錄到 MySQL 服務器后,可以使用 UPDATE 語句修改 MySQL 數(shù)據(jù)庫的 user 表的 authentication_string 字段,從而修改用戶的密碼。
使用 UPDATA 語句修改 root 用戶密碼的語法格式如下:
UPDATE mysql.user set authentication_string = PASSWORD ("rootpwd) WHERE User = "root" and Host="localhost";
新密碼必須使用 PASSWORD() 函數(shù)來加密。執(zhí)行UPDATE語句后,需要執(zhí)行FLUSH PRIVILEGES語句重新加載用戶權限。
使用SET語句修改root用戶的密碼
SET PASSWORD 語句可以用來重新設置其他用戶的登錄密碼或者自己使用的賬戶的密碼。使用 SET 語句修改密碼的語法結構如下:
SET PASSWORD = PASSWORD ("rootpwd");
MySQL修改密碼的3種方式
在使用數(shù)據(jù)庫時,我們也許會遇到 MySQL 需要修改密碼的情況,比如密碼太簡單需要修改等。
使用 SET PASSWORD 命令
步驟 1):輸入命令mysql -u root -p指定 root 用戶登錄 MySQL,輸入后按回車鍵輸入密碼。如果沒有配置環(huán)境變量,請在 MySQL 的 bin 目錄下登錄操作。
步驟 2):使用 SET PASSWORD 修改密碼命令格式為 set password for username @localhost = password(newpwd);
,其中 username 為要修改密碼的用戶名,newpwd 為要修改的新密碼。如圖所示。
步驟 3):輸入quit;命令退出 MySQL 重新登錄,輸入新密碼“root”登錄就可以了;
使用mysqladmin修改密碼
使用 mysqladmin 命令修改 MySQL 的 root 用戶密碼格式為 mysqladmin -u用戶名 -p舊密碼 password 新密碼。
注意:下圖修改密碼的命令中 -uroot 和 -proot 是整體,不要寫成 -u root -p root,-u 和 root 間可以加空格,但是會有警告出現(xiàn),所以就不要加空格了。
UPDATE直接編輯user表
步驟 1):輸入命令mysql -u root -p指定 root 用戶登錄 MySQL,輸入后按回車鍵輸入密碼。如果沒有配置環(huán)境變量,請在 MySQL 的 bin 目錄下登錄操作。
步驟 2):輸入use mysql;命令連接權限數(shù)據(jù)庫。
步驟 3):輸入命令update mysql.user set authentication_string=password('新密碼') where user='用戶名' and Host ='localhost';設置新密碼。
步驟 4):輸入 flush privileges; 命令刷新權限。
步驟 5):輸入quit;命令退出 MySQL 重新登錄,此時密碼已經(jīng)修改為剛才輸入的新密碼了。
MySQL忘記root密碼解決方案
在忘記 MySQL 密碼的情況下,可以通過 --skip-grant-tables 關閉服務器的認證,然后重置 root 的密碼,具體操作步驟如下。
步驟 1):關閉正在運行的 MySQL 服務。打開 cmd 進入 MySQL 的 bin 目錄。
步驟 2):輸入mysqld --console --skip-grant-tables --shared-memory 命令。–skip-grant-tables 會讓 MySQL 服務器跳過驗證步驟,允許所有用戶以匿名的方式,無需做密碼驗證就可以直接登錄 MySQL 服務器,并且擁有所有的操作權限。
步驟 3):上一個 DOS 窗口不要關閉,打開一個新的 DOS 窗口,此時僅輸入 mysql 命令,不需要用戶名和密碼,即可連接到 MySQL。
步驟 4):輸入命令 update mysql.user set authentication_string=password('root') where user='root' and Host ='localhost'; 設置新密碼。
注意:MySQL 5.7 版本中的 user 表里已經(jīng)去掉了 password 字段,改為了 authentication_string。
步驟 5):刷新權限(必須步驟),輸入flush privileges;命令。
步驟 6):因為之前使用 --skip-grant-tables 啟動,所以需要重啟 MySQL 服務器去掉 --skip-grant-tables。輸入無誤后輸入quit;命令退出 MySQL 服務。
步驟 7):重啟 MySQL 服務,使用用戶名 root 和剛才設置的新密碼 root 登錄就可以了。
MySQL權限控制實現(xiàn)原理
MySQL 權限表在數(shù)據(jù)庫啟動時載入內(nèi)存,用戶通過身份認證后,系統(tǒng)會在內(nèi)存中進行相應權限的存取。當 MySQL 允許一個用戶執(zhí)行各種操作時,它將首先核實該用戶向 MySQL 服務器發(fā)送的連接請求,然后確認用戶的操作請求是否被允許。
當用戶進行連接時,MySQL 實現(xiàn)權限控制主要有以下兩個階段:
連接核實階段
登錄 MySQL 服務器時,客戶端連接請求中會提供用戶名稱、主機地址和密碼,MySQL 服務器會使用 user 表中的 Host、User 和 authentication_string (MySQL 5.7 版本之前是 Password)字段執(zhí)行身份檢查。
只有客戶端請求的主機名和用戶名在 user 表中有匹配的記錄,并且密碼正確時,MySQL 服務器才會通過身份認證,接受連接,否則拒絕連接。
MySQL 通過 IP 地址和用戶名聯(lián)合進行身份認證。
- 例如 MySQL 安裝后默認創(chuàng)建的用戶 root@localhost,表示用戶 root 只能從本地(localhost)進行連接時才能通過認證。此用戶從其它任何主機對數(shù)據(jù)庫進行連接時都將被拒絕。也就是說,用戶名相同,IP 地址不同,MySQL 則將其視為不同的用戶。
服務器接受連接后進入請求核實階段等待用戶請求。如果連接核實沒有通過,服務器則完全拒絕訪問。
請求核實階段
建立連接后,服務器進入請求核實階段,對在此連接上的每個請求,服務器都會檢查用戶是否有足夠的權限來執(zhí)行它。這正是授權表中的權限列發(fā)揮作用的地方。
權限按照以下權限表的順序得到數(shù)據(jù)庫權限:user→db→tables_priv→columns_priv→procs_priv。在這幾個權限表中,權限范圍依次遞減,全局權限覆蓋局部權限。
請求核實的過程如下所示:
- 用戶向 MySQL 發(fā)出操作請求。
- MySQL 首先檢查 user 表,匹配 User、Host 字段值,查看請求的全局權限在 user 表中是否被授權。授權則允許操作執(zhí)行,如果指定的權限在 user 表中沒有被授權。MySQL 將檢查 db 表。
- db 表是下一安全層級,其中的權限限定于數(shù)據(jù)庫層級,在該層級的 SELECT 權限允許用戶查看指定數(shù)據(jù)庫的所有表中的數(shù)據(jù)。MySQL 檢查 db 權限表中的權限信息,匹配 User、Host 字段值,查看請求的數(shù)據(jù)庫級別的權限在 db 表中是否被授權。授權則允許操作執(zhí)行,否則 MySQL 繼續(xù)向下查找。
- MySQL 檢查 tables_priv 權限表中的權限信息,匹配 User、Host 字段值,查看請求的數(shù)據(jù)表級別的權限在 tables_priv 表中是否被授權。授權則允許操作執(zhí)行,否則 MySQL 繼續(xù)向下查找。
- MySQL 檢查 columns_priv 權限表中的權限信息,匹配 User、Host 字段值,查看請求的列級別的權限在 columns_priv 表中是否被授權。授權則允許操作執(zhí)行,否則 MySQL 繼續(xù)向下查找。
- 如果所有權限表都檢查完畢,還是沒有找到允許的權限操作,那么 MySQL 將返回錯誤信息,即用戶請求的操作不能執(zhí)行,操作失敗。
提示:上面提到 MySQL 通過向下層級的順序檢查權限表,但并不意味著所有的權限都要執(zhí)行該過程。例如,一個用戶登錄到 MySQL 服務器之后只執(zhí)行對 MySQL 的管理操作,此時只涉及管理權限,因此 MySQL 只檢查 user 表。