重學MySQL系列(四):10分鐘快速掌握MySQL用戶與權限管理

在這篇文章中,咱們來聊聊怎麼管理MySQL的用戶及如何爲不一樣用戶分配不一樣的管理權限,其實,在平常使用MySQL的過程當中,這部分的工做是由DBA(數據管理員)來完成的。mysql

而咱們做爲通常的開發人員,只要拿到分配好的帳號和密碼鏈接到MySQL服務器訪問特定的數據庫,並不涉及到用戶管理的內容。sql

不過,今天咱們不妨切換到一個DBA視角,一塊兒來詳細瞭解MySQL有關用戶及權限管理的相關知識。數據庫

權限數據表

MySQL中與系統用戶及用戶權限管理有關的信息都存儲在系統數據庫mysql中,這些數據表須要通過數據初始化,每一個數據表有特定的數據結構。安全

數據表初始化

在安裝好MySQL以後,須要初始化MySQL系統數據庫,好比咱們通常安裝好MySQL以後,MySQL會幫咱們建立默認的超級管理員root,咱們也可使用下面的語句在初始化時建立其餘帳號:bash

MySQL支持不少種不一樣的安裝方式,通常狀況下會幫咱們初始化mysql系統數據庫。服務器

bin/mysqld --initialize --user=mysql
bin/mysqld --initialize-insecure --user=mysql
複製代碼

權限表簡介

MySQL系統數據庫mysql中與用戶及權限相關的數據表一共有6張,下面表格這幾張數據表的說明。數據結構

系統數據庫mysql中除了與權限管理有關的數據外,還有其餘的數據表。函數

數據表 說明
user 用戶賬戶,全局特權和其餘非特權列
db 數據庫級別的管理權限
tables_priv 數據表級別的管理權限
columns_priv 數據列級別的管理權限
procs_priv 存儲過程及函數的使用權限
proxies_priv 代理用戶權限

權限表的結構

下面咱們來看這些數據表的更詳細表結構,咱們看到下面的數據表中的字段能夠大致分爲四類,分別爲scope columes,Privilege columns,Security columns,Resource control columnsui

scope columes用於限定是某個用戶,某個數據庫或者某個數據表,Privilege columns表示權限,在user表中表示全局權限,在db表中表示對某個數據庫的操做權限,而Security columnsResource control columns的字段則爲user表所獨有。編碼

user與db數據表

user數據表存儲的是用戶的帳號信息及全局權限信息,而db數據表存儲的是用戶對於具體數據庫的操做權限。

表名 user db
Scope columns Host Host
User Db
User
Privilege columns Select_priv Select_priv
Insert_priv Insert_priv
Update_priv Update_priv
Delete_priv Delete_priv
Index_priv Index_priv
Alter_priv Alter_priv
Create_priv Create_priv
Drop_priv Drop_priv
Grant_priv Grant_priv
Create_view_priv Create_view_priv
Show_view_priv Show_view_priv
Create_routine_priv Create_routine_priv
Alter_routine_priv Alter_routine_priv
Execute_priv Execute_priv
Ttrigger_priv Ttrigger_priv
Event_priv Event_priv
Create_tmp_table_priv Create_tmp_table_priv
Lock_tables_priv Lock_tables_priv
References_priv References_priv
Reload_priv
Shutdown_priv
Process_priv
File_priv
Show_db_priv
Super_priv
Repl_slave_priv
Repl_client_priv
Create_user_priv
Create_tablespace_priv
Security columns ssl_type
ssl_cipher
x509_issuer
x509_subject
plugin
authentication_string
password_expired
password_last_changed
password_lifetime
account_locked
Resource control columns max_questions
max_updates
max_connections
max_user_connections

上面是dbuser數據表的對比,在上面的對比中,咱們看到db數據表與user有相同的字段,這些字段在db數據表,表示某個用戶對某個數據表有哪些權限,而在user數據表中,則表示用戶的全局權限。

tables_priv與columns_priv數據表

tables數據用於存儲用戶對數據表的權限,而columns_priv數據用於存儲用戶對數據列的權限。

表名 tables_priv 與columns_priv
Scope columns Host Host
Db Db
User User
Table_name Table_name
Column_name
Privilege columns Table_priv Column_priv
Column_priv
Other columns Timestamp Timestamp
Grantor

procs_priv數據表

procs_priv數據表用於存儲用戶對自定義函數以及存儲過程的權限,其表結構比較簡單,以下所示:

表名 procs_priv
Scope columns Host
Db
User
Routine_name
Routine_type
Privilege columns Proc_priv
Other columns Timestamp
Grantor

在上面的字段中,Routine_typeENUM類型,其取值爲FUNCTIONPROCEDURE,而TimestampGrantor兩個字段暫時沒有什麼做用。

proxies_priv數據表

proxies_priv存儲的是代理用戶的關係數據,什麼是代理用戶?能夠簡單地理解爲一個用戶將本身的權限授予給被另外一個用戶使用,比較A用戶經過代理將權限授予B用戶使用,那麼B用戶則稱爲代理用戶。

proxies_priv數據表包含Host,User,Proxied_host,Proixed_user,Grantor,Timestamp,With_grant等字段。

用戶管理

介紹了與權限管理相關的數據表以後,咱們也知道MySQL將用戶存儲在哪一個數據表中,以及MySQL如何組織用戶的權限信息,接來在用戶管理這塊內容中,咱們來了解的是MySQL數據庫系統中,如何識別一個用戶,如何建立、修改、刪除用戶以及如何爲用戶設置密碼。

用戶

MySQL的用戶由用戶名(User)主機名(Host)組成,主機名錶示容許該用戶從哪臺主機鏈接到MySQL服務器,因此在MySQL中,表示一個用戶的格式以下所示:

# username表示用戶名,host_name表示主機名
'user_name'@'host_name'
複製代碼

好比我使用root帳號在MySQL本地服務器登陸,那麼此時的root帳號的用戶爲:

'root'@'localhost'
複製代碼

另外,在MySQL中,咱們可使用USER()CURRENT_USER()函數或者CURRENT_USER查詢當前的用戶,如:

mysql> SELECT USER();
mysql> SELECT CURRENT_USER();
mysql> SELECT CURRENT_USER;
複製代碼

上面兩個語句的查詢結果爲:

+----------------+
| user()         |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)

+----------------+
| current_user() |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)

+----------------+
| current_user   |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)

複製代碼

用戶名和主機名能夠惟一地肯定一個用戶,因此即便用戶名相同,主機名不一樣時,也表示兩個不一樣的用戶,好比下面的例子中用戶名雖然都是test,因爲主機名不一樣因此是兩個用戶。

'test'@'192.168.0.1'
'test'@'192.168.0.2'
複製代碼

當咱們在建立帳號沒有指定主機時,則主機名的值爲'%',這表示容許帳號從任意主機鏈接到MySQL服務器,好比:

'test'@'%'
複製代碼

在上面的示例中,用戶名和主機都是使用單引號括起來,不過,若是沒有特殊的字符,能夠不使用單引號,因此上面的用戶能夠這樣表示:

test@localhost
複製代碼

若是帶有橫槓(-),點(.),百分號(%),空格等特殊字符,則必須使用單引號,如:

# 正確示例
test@'192.168.0.1'
root@'%'

# 錯誤示例
test@192.168.0.1
test@%
複製代碼

從上面的示例中咱們也看到,用戶名和主機名是分別使用單引號括起來的,若是使用一個單引號把用戶名和主機號括號,則MySQL會認爲是整個看成用戶名,而主機名則用默認的'%',以下所示:

'root@localhost'

#上面的寫法,MySQL會解析爲
'root@localhost'@'%'
複製代碼

另外,爲了提升安全性,也能夠爲用戶設置登陸密碼,不過密碼並非必填的,不過爲了安全,最好仍是設置密碼。

MySQL用戶名的最大長度爲32個字符,這個字符長度在MySQL程序中是硬編碼的,因此即便咱們修改了存儲帳號的user數據表用戶名長度,也是沒有效果的。

查詢用戶權限

查詢用戶權限分爲兩種,一種是查詢本身當前登陸用戶的權限,一種是查詢其餘用戶的權限。

SHOW GRANTS [FOR user]
複製代碼

查詢當前用戶權限

不使用FOR子句的話,能夠當查詢當前登陸用戶的權限,好比我當前登陸了root用戶,使用下面的語句進行查詢:

mysql> SHOW GRANTS;
複製代碼

結果以下:

+---------------------------------------------------------------------+
| Grants for root@localhost                                           |
+---------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION |
| GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION        |
+---------------------------------------------------------------------+
2 rows in set (0.00 sec)
複製代碼

查詢其餘用戶權限

若是你的帳號有查詢其餘用戶信息的權限,那麼可使用FOR子句後面加上想查詢用戶的帳號信息,不過要注意的是,須要有查詢別人權限的權限,才能使用下面的語句。

mysql> SHOW GRANTS FOR 'test'@'localhost';
複製代碼

結果以下:

+------------------------------------------+
| Grants for 'test'@'localhost'                |
+------------------------------------------+
| GRANT USAGE ON *.* TO 'test'@'localhost' |
+------------------------------------------+
1 row in set (0.00 sec)
複製代碼

建立用戶

MySQL建立用戶使用CREATE USER語句,該語句比較複雜,其語句結構以下所示:

CREATE USER [IF NOT EXISTS]
    user [auth_option] [, user [auth_option]] ...
    [REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
    [WITH resource_option [resource_option] ...]
    [password_option | lock_option] ...

#參考咱們上面的介紹
user:
    (see Section 6.2.4, 「Specifying Account Names」)

auth_option: {
    IDENTIFIED BY 'auth_string'
  | IDENTIFIED WITH auth_plugin
  | IDENTIFIED WITH auth_plugin BY 'auth_string'
  | IDENTIFIED WITH auth_plugin AS 'auth_string'
  | IDENTIFIED BY PASSWORD 'auth_string'
}

tls_option: {
   SSL
 | X509
 | CIPHER 'cipher'
 | ISSUER 'issuer'
 | SUBJECT 'subject'
}

resource_option: {
    MAX_QUERIES_PER_HOUR count
  | MAX_UPDATES_PER_HOUR count
  | MAX_CONNECTIONS_PER_HOUR count
  | MAX_USER_CONNECTIONS count
}

password_option: {
    PASSWORD EXPIRE
  | PASSWORD EXPIRE DEFAULT
  | PASSWORD EXPIRE NEVER
  | PASSWORD EXPIRE INTERVAL N DAY
}

lock_option: {
    ACCOUNT LOCK
  | ACCOUNT UNLOCK
}
複製代碼

上面的語法看着好像很複雜,其實不少選項是能夠選擇的,好比最簡單的,咱們可使用下面的語句建立一個用戶:

mysql> CREATE USER 'test'@'localhost' IDENTIFIED BY '123456';
複製代碼

修改用戶

MySQL修改用戶的信息使用ALTER USER語句,其用法以下所示:

ALTER USER [IF EXISTS]
    user [auth_option] [, user [auth_option]] ...
    [REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
    [WITH resource_option [resource_option] ...]
    [password_option | lock_option] ...
複製代碼

從上面的用法中能夠看出,ALTER USER語句和CREATE USER語句基本相似,各類選項基本相同,所以咱們參考CREATE USER的用法。

好比咱們要修改當前用戶的密碼,能夠這樣:

mysql> ALTER USER USER() IDENTIFIED BY 'test123457';
複製代碼

刪除用戶

MySQL刪除用戶使用DROP USER語句,該語句用法以下:

DROP USER [IF EXISTS] user [, user] ...
複製代碼

從上面的語法看現,MySQL支持刪除一個或多個用戶,其用法以下所示:

mysql> DROP USER 'test'@'test.example.com','test1'@'test1.example.com';;
複製代碼

設置密碼

若是在建立用戶的時候沒有指定密碼,或者想從新設置某個用戶的密碼,可使用SET PASSWORD語句,該語句的用法以下所示:

SET PASSWORD [FOR user] = password_option

password_option: {
    'auth_string'
  | PASSWORD('auth_string')
}
複製代碼

上面的語句中,auth_string表示未加密的明文密碼,也可使用PASSWORD()函數進行加密,不過在MySQL5.7.6以後不推薦這種用法,在將來的版本這種用法會移除。

設置密碼語句中的FOR子句能夠省略,若是省略則表示修改當前用戶的密碼,如:

SET PASSWORD = "123456"
複製代碼

使用FOR子句,則能夠修改指定帳號的密碼,以下:

SET PASSWORD FOR CURRENT_USER() = "123456"
複製代碼

MySQL用戶管理中,並不推薦使用SET PASSWORD語句來設置用戶密碼,由於這個步驟在CREATE USERALTER USER即可以完成了。

受權管理

前面講了MySQL權限的存儲細節以及用戶管理的相關知識,對這些有所瞭解以後,咱們來詳細瞭解如何給用戶受權權限。

MySQL中,對於用戶的權限劃分能夠分爲兩種,一種是數據管理相關的權限,好比對數據庫、數據表進行操做,建立存儲過程和視圖的權限,另外一種是對用戶的管理權限,好比建立、刪除用戶,爲用戶分配權限。

用戶受權

MySQL爲咱們提供了GRANT語句進行受權管理,其語法結構以下所示:

GRANT
    priv_type [(column_list)]
      [, priv_type [(column_list)]] ...
    ON [object_type] priv_level
    TO user [auth_option] [, user [auth_option]] ...
    [REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
    [WITH {GRANT OPTION | resource_option} ...]

GRANT PROXY ON user
    TO user [, user] ...
    [WITH GRANT OPTION]

object_type: {
    TABLE
  | FUNCTION
  | PROCEDURE
}

priv_level: {
    *
  | *.*
  | db_name.*
  | db_name.tbl_name
  | tbl_name
  | db_name.routine_name
}

user:
    (see Section 6.2.4, 「Specifying Account Names」)

auth_option: {
    IDENTIFIED BY 'auth_string'
  | IDENTIFIED WITH auth_plugin
  | IDENTIFIED WITH auth_plugin BY 'auth_string'
  | IDENTIFIED WITH auth_plugin AS 'auth_string'
  | IDENTIFIED BY PASSWORD 'auth_string'
}

tls_option: {
    SSL
  | X509
  | CIPHER 'cipher'
  | ISSUER 'issuer'
  | SUBJECT 'subject'
}

resource_option: {
  | MAX_QUERIES_PER_HOUR count
  | MAX_UPDATES_PER_HOUR count
  | MAX_CONNECTIONS_PER_HOUR count
  | MAX_USER_CONNECTIONS count
}
複製代碼

執行的條件

爲別的用戶受權,當前用戶必須擁有受權的權限才能夠,好比咱們以普通用戶test登陸MySQL爲別的用戶分配權限,因爲test沒有這種權限,所以會報如下的錯誤:

ERROR 1045 (28000): Access denied for user 'test'@'localhost' (using password: NO)
複製代碼

建立用戶

使用GRANT進行受權時,若是該用戶不存在,能夠跟上GRANT語句後面跟上IDENTIFIED BY直接建立該用戶,不過若是在建立用戶時要設置更詳細的信息,則應該使用CREATE USER語句來建立用戶。

GRANT ALL ON *.* TO test_1@localhost IDENTIFIED BY "123456";
複製代碼

上面的語句在用戶不存在,會自動建立用戶。

權限的級別

在分配權限時,想分配什麼級別的權限,能夠加在關鍵字ON後面,其格式以下所示:

*
 *.*
 db_name.*
 db_name.tbl_name
 tbl_name
 db_name.routine_name
複製代碼

好比我想給test@localhost用戶分配school數據庫的student表查詢權限,能夠這樣寫:

mysql> GRANT SELECT ON school.student TO 'test'@'localhost'複製代碼

權限列表

下面是使用GRANT語句能夠授予的所有權限,不一樣的權限有不一樣的做用域,好比有的是全局權限,有的只做用於數據庫等,以下所示:

權限 權限說明及做用的級別
ALTER[PRIVILEGES] 除了GRANT OPTION和PROXY以外,以指定的訪問級別授予全部特權。
ALTER 修改權限,做用於全局,數據庫,數據表
ALTER_ROUTINE 修改存儲過程,做用於全局,數據庫,存儲過程
CREATE 建立權限,做用於全局,數據庫,數據表
CREATE_ROUTINE 建立存儲過程的權限,做用於全局,數據庫
CREATE_TABLESPACE 表空間和日誌文件組的建立、更改、刪除,全局權限
CREATE_TEMPORARY_TABLES 建立臨時表的權限,做用於數據庫,數據表
CREATE_USER 建立、刪除,重命用和移除用戶權限的權限,全局權限
CREATE_VIEW 建立視圖權限,做用於全局,數據庫,數據表
DELETE 刪除數據權限,做用於全局,數據庫,數據表
DROP 刪除數據庫、數據表、視圖的權限,做用於全局,數據庫,數據表
EVENT 使用事件的權限,做用於全局,數據庫
EXECUTE 執行存儲過程的權限,做用於全局,數據庫,存儲過程
FILE 讀取或寫入文件的權限,全局權限
GRANT_OPTION 容許受權或取消受權的權限,做用於全局,數據庫,數據表,存儲過程,代理
INDEX 使用索引的權限,做用於全局,數據庫,數據表
INSERT 寫入權限,做用於全局,數據庫,數據表,數據列
LOCK_TABLES 在執行SELECT時能夠啓動LOCK_TABLES的權限,全局或數據庫級別的權限
PROCESS 使用SHOW PROCESSLIST查詢所有存儲過程的權限,全局權限
PROXY 啓用用戶代理,做用級別從用戶到用戶
REFERENCES 建立外健權限,做用於全局,數據庫,數據表,數據列
RELOAD 啓動FLUSH操做,全局權限
REPLICATION CLIENT 使用戶可以詢問主服務器或從服務器在哪裏,全局權限
REPLICATION SLAVE 啓用複製從屬服務器以從主服務器讀取二進制日誌事件,全局權限
SELECT 查詢權限,做用於全局,數據庫,數據表,數據列
SHOW_DATABASES 查詢所有數據庫,全局權限
SHOW_VIEWS 啓用使用SHOW CREATE VIEW,做用於全局,數據庫,數據表
SHUTDOWN 關閉數據庫服務器權限,全局權限
SUPER 啓用其餘管理操做的使用,例如CHANGE MASTER TO,KILL,PURGE BINARY LOGS,SET GLOBAL和mysqladmin debug命令。 全局權限
TRIGGER 啓用觸發器的權限,做用於全局,數據庫,數據表
UPDATE 更新權限,做用於全局,數據庫,數據表,數據列
USAGE 無特權

建立超級管理員

使用All權限分配給用戶時,用戶雖然擁有全部數據庫的操做權限,但並無帳號管理等權限,若是想建立一直跟root同樣的超級管理員,能夠加上WITH GRANT OPTION參數,以下所示:

mysql> GRANT ALL ON *.* TO 'super'@'localhost' WITH GRANT OPTION
複製代碼

刪除用戶權限

刪除權限與上面的受權是反向操做,能夠刪除不一樣級別的權限,就像上面能夠授予不一樣級別的權限同樣。

刪除權限使用REVOKE語句,其語法結構以下:

REVOKE
    priv_type [(column_list)]
      [, priv_type [(column_list)]] ...
    ON [object_type] priv_level
    FROM user [, user] ...

REVOKE ALL [PRIVILEGES], GRANT OPTION
    FROM user [, user] ...

REVOKE PROXY ON user
    FROM user [, user] ...
複製代碼

刪除數據庫級別的權限:

mysql > REVOKE CREATE,DROP ON expenses.* FROM 'custom'@'host47.example.com';
複製代碼

刪除用戶的所有權限:

mysql> REVOKE ALL ON *.* FROM 'finley'@'%.example.com';
複製代碼

小結

MySQL做爲數據庫管理系統,裏面保存企業的重要業務數據,所以保證數據庫的安全性很是重要,如何保證數據庫的安全性呢?用戶和用戶權限管理是一個很重要的方面。


若是你以爲文章不錯,歡迎掃碼關注,你的關注就是我寫做的最大動力

相關文章
相關標籤/搜索