MySQL 8.0用戶和角色管理

MySQL 8.0 正式版目前已發佈,MySQL 8.0 增長了不少新的功能,具體可參考「MySQL 8.0 正式版 8.0.11 發佈!」一文。mysql

MySQL 8.0 在用戶管理方面增長了角色管理,默認的密碼加密方式也作了調整,由以前的 SHA1 改成了 SHA2。同時加上 MySQL 5.7 的禁用用戶和用戶過時的功能,MySQL 在用戶管理方面的功能和安全性都較以前版本大大的加強了。sql

在本教程中,咱們將介紹 MySQL 下用戶管理上的一些新特性和如何使用角色來簡化權限管理。數據庫

注:本教程大部分特性要 MySQL 8.0 + 以上版本才支持。安全

MySQL 用戶管理

驗證插件和密碼加密方式的變化

在 MySQL 8.0 中,caching_sha2_password 是默認的身份驗證插件而不是以前版本的 mysql_native_password,默認的密碼加密方式是 SHA2bash

mysql> show variables like 'default_authentication_plugin';
+-------------------------------+-----------------------+
| Variable_name                 | Value                 |
+-------------------------------+-----------------------+
| default_authentication_plugin | caching_sha2_password |
+-------------------------------+-----------------------+
1 row in set (0.00 sec)

mysql> select user,host,plugin from mysql.user;
+------------------+-----------+-----------------------+
| user             | host      | plugin                |
+------------------+-----------+-----------------------+
| root             | %         | caching_sha2_password |
| mysql.infoschema | localhost | mysql_native_password |
| mysql.session    | localhost | mysql_native_password |
| mysql.sys        | localhost | mysql_native_password |
| root             | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+
5 rows in set (0.00 sec)複製代碼

若是須要保持以前的驗證方式並保持以前版本的密碼加密方式須要在配置文件 my.cnf 中修改如下配置項並重啓服務後生效。服務器

[mysqld]
default_authentication_plugin = mysql_native_password複製代碼

注:此選項暫不支持 MySQL 8.0 動態修改特性。session

將 MySQL 8.0 中已有的 SHA2 密碼修改成 SHA1 的模式。app

# 更新用戶的密碼加密方式爲以前版本的方式
mysql> ALTER USER 'root'@'127.0.0.1' IDENTIFIED WITH mysql_native_password BY 'password';
# 刷新權限
mysql> FLUSH PRIVILEGES;複製代碼

注:若是沒有特殊的緣由,建議使用更安全的新加密方式。運維

用戶受權和修改密碼

MySQL 8.0 的用戶受權語句和以前版本有所區別,老版本的經常使用受權語句在 MySQL 8.0 版本中 已不能使用,如使用舊版本受權語句會報錯。wordpress

  • 在 MySQL 8.0 用以前版本受權語句建立用戶。

mysql> GRANT ALL PRIVILEGES ON *.* TO `mike`@`%` IDENTIFIED BY '000000' WITH GRANT OPTION;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IDENTIFIED BY '000000' WITH GRANT OPTION' at line 1複製代碼
  • 在 MySQL 8.0 版本中正確受權語句。

mysql> CREATE USER 'mike'@'%' IDENTIFIED BY '000000';
mysql> GRANT ALL ON *.* TO 'mike'@'%' WITH GRANT OPTION;複製代碼

密碼過時時間管理

MySQL 從 5.6.6 開始引入密碼自動過時的新功能,並在 MySQL 5.7.4 版本中改進了用戶密碼過時時間這個特性。如今能夠經過一個全局變量 default_password_lifetime來設置一個全局的自動密碼過時策略。

default_password_lifetime 其默認值爲 0,表示禁用自動密碼過時。default_password_lifetime 的值如是是正整數 N ,則表示容許的設置密碼生存週期 爲 N,單位爲天 。

  • default_password_lifetime 全局密碼到期策略默認爲永久,不過時。

mysql> show variables like 'default_password_lifetime';
+---------------------------+-------+
| Variable_name             | Value |
+---------------------------+-------+
| default_password_lifetime | 0     |
+---------------------------+-------+
1 row in set (0.00 sec)複製代碼
  • 若是你要創建一個全局策略,讓全部用戶的密碼的使用期限爲六個月,可在服務端配置文件 my.cnf 中修改 default_password_lifetime 配置項的值爲 180。

[mysqld]
default_password_lifetime=180複製代碼
  • 若是你要恢復全局策略,讓全部用戶的密碼永不過時,可在服務端配置文件 my.cnf 中修改 default_password_lifetime 配置項的值爲 0。

[mysqld]
default_password_lifetime=0複製代碼
  • default_password_lifetime 參數是支持永久動態設置的,你也能夠用如下命令在 MySQL 命令行下直接設置生效。

# 設置默認密碼過時策略爲 180 天后過時
mysql> SET PERSIST default_password_lifetime = 180;

# 設置默認密碼過時策略爲永不過時
mysql> SET PERSIST default_password_lifetime = 0;

# MySQL 8.0 永久動態修改參數會保存在配置文件 mysqld-auto.cnf 中,保存的格式爲JSON串。
$ cat  /var/lib/mysql/mysqld-auto.cnf
{ "Version" : 1 , "mysql_server" : { "default_password_lifetime" : { "Value" : "180" , "Metadata" : { "Timestamp" : 1525663928688419 , "User" : "root" , "Host" : "" } } } }複製代碼
  • 建立和修改帶有密碼過時時間的用戶示例

建立或修改一個用戶的密碼過時時間爲 90 天。

mysql> CREATE USER 'mike'@'%' IDENTIFIED BY '000000' PASSWORD EXPIRE INTERVAL 90 DAY;
mysql> ALTER USER `mike`@`%` PASSWORD EXPIRE INTERVAL 90 DAY;複製代碼

建立或修改一個用戶的密碼過時時間爲永不過時。

mysql> CREATE USER 'mike'@'%' PASSWORD EXPIRE NEVER;
mysql> ALTER USER 'mike'@'%' PASSWORD EXPIRE NEVER;複製代碼

建立或修改一個遵循全局到期策略的用戶。

mysql> CREATE USER 'mike'@'%' PASSWORD EXPIRE DEFAULT;
mysql> ALTER USER 'mike'@'%' PASSWORD EXPIRE DEFAULT;複製代碼

查看用戶的密碼過時時間。

mysql> select user,host,password_last_changed,password_lifetime,password_expired from mysql.user;
+------------------+-----------+-----------------------+-------------------+------------------+
| user             | host      | password_last_changed | password_lifetime | password_expired |
+------------------+-----------+-----------------------+-------------------+------------------+
| mike             | %         | 2018-05-07 11:13:39   |                90 | N                |
| root             | %         | 2018-05-04 16:46:05   |              NULL | N                |
| mysql.infoschema | localhost | 2018-05-04 16:45:55   |              NULL | N                |
| mysql.session    | localhost | 2018-05-04 16:45:55   |              NULL | N                |
| mysql.sys        | localhost | 2018-05-04 16:45:55   |              NULL | N                |
| root             | localhost | 2018-05-04 16:46:05   |              NULL | N                |
+------------------+-----------+-----------------------+-------------------+------------------+
6 rows in set (0.00 sec)複製代碼

鎖定/解鎖用戶賬戶

從 MySQL 5.7.8 開始,用戶管理方面添加了鎖定/解鎖用戶賬戶的新特性。下面咱們就來看下這個特性的一些具體示例。

  • 建立一個帶賬戶鎖的用戶

mysql> CREATE USER 'mike-temp1'@'%' IDENTIFIED BY '000000' ACCOUNT LOCK;複製代碼

接下來嘗試用新建立的用戶登錄,此時會獲得一個 ERROR 3118 錯誤消息提示。

$ mysql -umike-temp1 -p000000
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 3118 (HY000): Access denied for user 'mike-temp1'@'172.22.0.1'. Account is locked.複製代碼

若是你須要解鎖此用戶,此時就須要使用如下語句對其進行解鎖了。

mysql> ALTER USER 'mike-temp1'@'%' ACCOUNT UNLOCK;
Query OK, 0 rows affected (0.00 sec)複製代碼

如今,這個用戶就已經解鎖,再次嘗試登錄。

$ mysql -umike-temp1 -p000000
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.0.11 MySQL Community Server - GPL

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>複製代碼
  • 修改一個用戶爲鎖定狀態

若是用戶已創建,你也能夠這樣鎖定用戶賬戶。

mysql> ALTER USER 'mike'@'%' ACCOUNT LOCK;
Query OK, 0 rows affected (0.00 sec)複製代碼

設置 MySQL 用戶密碼重用策略

從 MySQL 8.0 開始容許限制重複使用之前的密碼。能夠根據密碼更改次數、已用時間或二者來創建密碼重用限制。賬戶的密碼歷史由過去分配的密碼組成,MySQL 能夠限制今後歷史記錄中選擇新密碼。

  • 若是根據密碼更改次數限制賬戶,則沒法從指定數量的最新密碼中選擇新密碼。例如:若是密碼更改的最小數量設置爲 3,則新密碼不能與任何最近的3個密碼相同。

  • 若是根據密碼修改時間來限制賬戶,則沒法將指定時間歷史記錄中的密碼中選擇爲新密碼。例如:若是密碼重用間隔設置爲 60,則新密碼不得在最近 60 天內選擇的密碼相同。

注:空密碼不記錄在密碼歷史記錄中,並隨時能夠重複使用。

要創建全局密碼重用策略,可修改 password_historypassword_reuse_interval 系統變量。該變量可在服務配置文件 my.cnf 中配置,以禁止重複使用最近 6 個密碼或最近 180 天內使用過的任何密碼爲例。

[mysqld]
password_history=6
password_reuse_interval=180複製代碼

該參數是支持永久動態設置,也能夠直接用下面語句進行設置。

mysql> SET PERSIST password_history = 6;
mysql> SET PERSIST password_reuse_interval = 180;複製代碼

MySQL 角色管理

MySQL 數據庫中一般都會出現多個擁有相同權限集合的用戶,在以前版本中只有分別向多個用戶授予和撤銷權限才能實現單獨更改每一個用戶的權限。在用戶數量比較多的時候,這樣的操做是很是耗時的。

MySQL 8.0 爲了用戶權限管理更容易,提供了一個角色管理的新功能。角色是指定的權限集合,和用戶賬戶同樣能夠對角色進行權限的授予和撤消。若是用戶被授予角色權限,則該用戶擁有該角色的權限。

MySQL 8.0 提供的角色管理功能以下:

CREATE ROLE 角色建立
DROP ROLE 角色刪除
GRANT 爲用戶和角色分配權限
REVOKE 爲用戶和角色撤銷權限
SHOW GRANTS 顯示用戶和角色的權限
SET DEFAULT ROLE 指定哪些賬戶角色默認處於活動狀態
SET ROLE 更改當前會話中的活動角色
CURRENT_ROLE() 顯示當前會話中的活動角色複製代碼

建立角色並授予用戶角色權限

這裏咱們以幾種常見場景爲例。

  • 應用程序須要讀/寫權限。

  • 運維人員須要徹底訪問數據庫。

  • 部分開發人員須要讀取權限。

  • 部分開發人員須要讀寫權限。

若是要向多個用戶授予相同的權限集,則應按以下步驟來進行。

  • 建立新的角色

  • 授予角色權限

  • 授予用戶角色

首先,咱們建立四個角色。爲了清楚區分角色的權限,建議將角色名稱命名得比較直觀。

mysql> CREATE ROLE 'app', 'ops', 'dev_read', 'dev_write';複製代碼

注:角色名稱格式相似於由用戶和主機部分組成的用戶賬戶,如:role_name@host_name。若是省略主機部分,則默認爲 「%」,表示任何主機。

建立好角色後,咱們就給角色授予對應的權限。要授予角色權限,您可使用 GRANT語句。

# 如下語句是向 app 角色授予 wordpress 數據庫的讀寫權限
mysql> GRANT SELECT, INSERT, UPDATE, DELETE ON wordpress.* TO 'app';
# 如下語句是向 ops 角色授予 wordpress 數據庫的全部權限
mysql> GRANT ALL PRIVILEGES ON wordpress.* TO 'ops';
# 如下語句是向 dev_read 角色授予 wordpress 數據庫的只讀權限
mysql> GRANT SELECT ON wordpress.* TO 'dev_read';
# 如下語句是向 dev_write 角色授予 wordpress 數據庫的寫權限
mysql> GRANT INSERT, UPDATE, DELETE ON wordpress.* TO 'dev_write';複製代碼

注:這裏假定需受權的數據庫名稱爲 wordpress。

最後根據實際狀況,咱們將指定用戶加入到對應的角色。假設須要一個應用程序使用的賬戶、一個運維人員賬戶、一個是開發人員只讀賬戶和兩個開發人員讀寫賬戶。

  • 建立新用戶

# 應用程序賬戶
mysql> CREATE USER 'app01'@'%' IDENTIFIED BY '000000';
# 運維人員賬戶
mysql> CREATE USER 'ops01'@'%' IDENTIFIED BY '000000';
# 開發人員只讀賬戶
mysql> CREATE USER 'dev01'@'%' IDENTIFIED BY '000000';
# 開發讀寫賬戶
mysql> CREATE USER 'dev02'@'%' IDENTIFIED BY '000000';
mysql> CREATE USER 'dev03'@'%' IDENTIFIED BY '000000';複製代碼
  • 給用戶分配角色

mysql> GRANT app TO 'app01'@'%';
mysql> GRANT ops TO 'ops01'@'%';
mysql> GRANT dev_read TO 'dev01'@'%';複製代碼

若是要將多個用戶同時加入多個角色,可使用相似語句。

mysql> GRANT dev_read, dev_write TO 'dev02'@'%', 'dev03'@'%';複製代碼

檢查角色權限

要驗證角色是否正確分配,可使用 SHOW GRANTS 語句。

mysql> SHOW GRANTS FOR 'dev01'@'%';
+-------------------------------------+
| Grants for dev01@%                  |
+-------------------------------------+
| GRANT USAGE ON *.* TO `dev01`@`%`   |
| GRANT `dev_read`@`%` TO `dev01`@`%` |
+-------------------------------------+
2 rows in set (0.00 sec)複製代碼

正如你所看到的,和以前版本不一樣的是 SHOW GRANTS 只返回授予角色。若是要顯示角色所表明的權限,須要加上 USING 子句和受權角色的名稱。

mysql> SHOW GRANTS FOR 'dev01'@'%' USING dev_read;
+----------------------------------------------+
| Grants for dev01@%                           |
+----------------------------------------------+
| GRANT USAGE ON *.* TO `dev01`@`%`            |
| GRANT SELECT ON `wordpress`.* TO `dev01`@`%` |
| GRANT `dev_read`@`%` TO `dev01`@`%`          |
+----------------------------------------------+
3 rows in set (0.00 sec)複製代碼

設置默認角色

如今,若是您使用 dev01 用戶賬戶鏈接到 MySQL,並嘗試訪問 wordpress 數據庫會出現如下錯誤。

$ mysql -u dev01 -p000000
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 8.0.11 MySQL Community Server - GPL

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> use wordpress;
ERROR 1044 (42000): Access denied for user 'dev01'@'%' to database 'wordpress'複製代碼

這是由於在向用戶賬戶授予角色後,當用戶賬戶鏈接到數據庫服務器時,它並不會自動使角色變爲活動狀態。

# 調用 CURRENT_ROLE() 函數查看當前角色。
mysql> SELECT current_role();
+----------------+
| current_role() |
+----------------+
| NONE           |
+----------------+
1 row in set (0.00 sec)複製代碼

這裏返回 NONE,就意味着當前沒有啓用任何角色。要在每次用戶賬戶鏈接到數據庫服務器時指定哪些角色應該處於活動狀態,需用使用 SET DEFAULT ROLE 語句來指定。

# 如下語句將把 dev01 賬戶分配的全部角色都設置爲默認值。
mysql> SET DEFAULT ROLE ALL TO 'dev01'@'%';複製代碼

再次使用 dev01 用戶賬戶鏈接到 MySQL 數據庫服務器並調用 CURRENT_ROLE() 函數,您將看到 dev01 用戶賬戶的默認角色。

$ mysql -u dev01 -p000000
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 8.0.11 MySQL Community Server - GPL

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

# 查看 dev01 用戶賬戶的默認角色。
mysql> SELECT current_role();
+----------------+
| current_role() |
+----------------+
| `dev_read`@`%` |
+----------------+
1 row in set (0.00 sec)複製代碼

最後經過將當前數據庫切換到 wordpress 數據庫,並執行 SELECT 語句和 DELETE 語句來測試 dev01 賬戶的權限。

mysql> use wordpress;
Database changed

mysql> select  count(*) from wp_terms;
+----------+
| count(*) |
+----------+
|      357 |
+----------+
1 row in set (0.00 sec)

mysql> DELETE from wp_terms;
ERROR 1142 (42000): DELETE command denied to user 'dev01'@'172.22.0.1' for table 'wp_terms'複製代碼

如上面結果所示,當咱們發出 DELETE 語句時,就收到一個錯誤。由於 dev01 用戶賬戶只有讀取訪問權限。

設置活動角色

用戶賬戶能夠經過指定哪一個受權角色處於活動狀態來修改當前用戶在當前會話中的有效權限。

  • 將活動角色設置爲 NONE,表示沒有活動角色。

mysql> SET ROLE NONE;複製代碼
  • 將活動角色設置爲全部授予的角色。

mysql> SET ROLE ALL;複製代碼
  • 將活動角色設置爲由 SET DEFAULT ROLE 語句設置的默認角色。

mysql> SET ROLE DEFAULT;複製代碼
  • 同時設置多個活動的角色。

mysql> SET ROLE granted_role_1, granted_role_2, ...複製代碼

撤消角色或角色權限

正如能夠受權某個用戶的角色同樣,也能夠從用戶賬戶中撤銷這些角色。要從用戶賬戶中撤銷角色須要使用 REVOKE 語句。

mysql> REVOKE role FROM user;複製代碼

REVOKE 也能夠用於修改角色權限。這不只影響角色自己權限,還影響任何授予該角色的用戶權限。假設想臨時讓全部開發用戶只讀,可使用 REVOKE 從 dev_write 角色中撤消修改權限。咱們先來看下用戶賬戶 dev02 撤消前的權限。

mysql> SHOW GRANTS FOR 'dev02'@'%' USING 'dev_read', 'dev_write';
+----------------------------------------------------------------------+
| Grants for dev02@%                                                   |
+----------------------------------------------------------------------+
| GRANT USAGE ON *.* TO `dev02`@`%`                                    |
| GRANT SELECT, INSERT, UPDATE, DELETE ON `wordpress`.* TO `dev02`@`%` |
| GRANT `dev_read`@`%`,`dev_write`@`%` TO `dev02`@`%`                  |
+----------------------------------------------------------------------+
3 rows in set (0.00 sec)複製代碼

接下來從 dev_write 角色中撤消掉修改權限。

mysql> REVOKE INSERT, UPDATE, DELETE ON wordpress.* FROM 'dev_write';
Query OK, 0 rows affected (0.03 sec)複製代碼

最後咱們在來看看 dev02 用戶賬戶當前權限。

mysql> SHOW GRANTS FOR 'dev02'@'%' USING 'dev_read', 'dev_write';
+-----------------------------------------------------+
| Grants for dev02@%                                  |
+-----------------------------------------------------+
| GRANT USAGE ON *.* TO `dev02`@`%`                   |
| GRANT SELECT ON `wordpress`.* TO `dev02`@`%`        |
| GRANT `dev_read`@`%`,`dev_write`@`%` TO `dev02`@`%` |
+-----------------------------------------------------+
3 rows in set (0.00 sec)複製代碼

從上面的結果能夠看出,角色中撤銷權限會影響到該角色中任何用戶的權限。所以 dev02 如今已經沒有表修改權限(INSERT,UPDATE,和 DELETE 權限已經去掉)。若是要恢復角色的修改權限,只需從新授予它們便可。

# 授予 dev_write 角色修改權限。
mysql> GRANT INSERT, UPDATE, DELETE ON wordpress.* TO 'dev_write';

# 再次查看 dev02 用戶權限,修改權限已經恢復。
mysql> SHOW GRANTS FOR 'dev02'@'%' USING 'dev_read', 'dev_write';
+----------------------------------------------------------------------+
| Grants for dev02@%                                                   |
+----------------------------------------------------------------------+
| GRANT USAGE ON *.* TO `dev02`@`%`                                    |
| GRANT SELECT, INSERT, UPDATE, DELETE ON `wordpress`.* TO `dev02`@`%` |
| GRANT `dev_read`@`%`,`dev_write`@`%` TO `dev02`@`%`                  |
+----------------------------------------------------------------------+
3 rows in set (0.00 sec)複製代碼

刪除角色

要刪除一個或多個角色,可使用 DROP ROLE 語句。

mysql> DROP ROLE 'role_name', 'role_name', ...;複製代碼

如同 REVOKE 語句同樣,刪除角色會從受權它的每一個賬戶中撤消該角色。例如,要刪除 dev_read,dev_write角色,可以使用如下語句。

mysql> DROP ROLE 'dev_read', 'dev_write';複製代碼

複製用戶賬戶權限到另外一個用戶

MySQL 8.0 將每個用戶賬戶視爲角色,所以能夠將用戶賬戶授予另外一個用戶賬戶。例如:將一開發人員賬號權限複製到另外一開發人員賬號。

  • 建立一個新的開發用戶賬戶

mysql> CREATE USER 'dev04'@'%' IDENTIFIED BY '000000';
Query OK, 0 rows affected (0.04 sec)複製代碼
  • 將 dev02 用戶賬戶的權限複製到 dev04 用戶賬戶

mysql> GRANT 'dev02'@'%' TO 'dev04'@'%';
Query OK, 0 rows affected (0.09 sec)複製代碼
  • 查看 dev04 用戶賬戶的權限

mysql> SHOW GRANTS FOR 'dev04'@'%' USING 'dev02';
+----------------------------------------------------------------------+
| Grants for dev04@%                                                   |
+----------------------------------------------------------------------+
| GRANT USAGE ON *.* TO `dev04`@`%`                                    |
| GRANT SELECT, INSERT, UPDATE, DELETE ON `wordpress`.* TO `dev04`@`%` |
| GRANT `dev02`@`%` TO `dev04`@`%`                                     |
+----------------------------------------------------------------------+
3 rows in set (0.00 sec)複製代碼

參考文檔

http://www.google.com
http://t.cn/RuTna0t
http://t.cn/RuTnEPH
http://t.cn/RuTnFGz
http://t.cn/RuTnFGz


若是你以爲內容很贊,還等什麼?快快長按打賞吧,iOS的土豪們也是能夠的喲!




相關文章
相關標籤/搜索