MySQL8.0角色管理—(二)

  • 2020 年 2 月 25 日
  • 筆記

//

MySQL8.0角色管理—(二)

//

昨天介紹了MySQL8.0中角色的概念,簡單講了角色的部分操作,今天來看看角色管理部分的關鍵內容。

01

創建角色

新創建的角色暫時是被鎖定的,沒有密碼。該角色的屬性可以被擁有create user權限的用戶來修改。處於鎖定狀態下的賬號,不能被用來對服務器進行驗證,也就是無法直接登錄服務器,解鎖之後的角色,就可以登錄服務器了。

昨天的文章中,我們創建了兩個角色,並將角色分配給兩個賬號,如下:

角色:role_ro

權限:select

賬號:yeyz_ro

角色2:role_rw

權限:select,update,insert,delete

賬號:yeyz_rw

當我們使用yeyz_ro的賬號去登錄數據庫的時候,可以發現:

1、賬號可以登錄

2、無法執行任何查詢操作,甚至連我們的數據庫yeyz都看不到。

如下:

192:~ root# /usr/local/mysql_8.0/bin/mysql -uyeyz_ro -pyeyz -h127.0.0.1 --socket=/data/mysql_5306/tmp/mysql.sock --port=5306  ........  Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.    mysql> show databases;  +--------------------+  | Database           |  +--------------------+  | information_schema |  +--------------------+  1 row in set (0.01 sec)    mysql> use yeyz;  ERROR 1044 (42000): Access denied for user 'yeyz_ro'@'%' to database 'yeyz'  

這個原因是由於當前沒有角色被"激活"導致的,如下:

mysql> select current_role();  +----------------+  | current_role() |  +----------------+  | NONE           |  +----------------+  1 row in set (0.00 sec)  

那麼如何"激活"角色呢?

02

如何激活角色?

使用set default role語法可以激活用戶進行身份認證時所需的角色,具體的方法如下:

mysql> set default role 'role_ro' to yeyz_ro@'%';  Query OK, 0 rows affected (0.00 sec)  

將role_ro這個角色設置為yeyz_ro的默認激活角色,這樣,就可以使用yeyz_ro的用戶來訪問對應的數據庫了,該用戶將擁有role_ro這個角色的權限。如下,再次用yeyz_ro登錄MySQL服務,查看當前的角色:

mysql> select current_role();  +----------------+  | current_role() |  +----------------+  | `role_ro`@`%`  |  +----------------+  1 row in set (0.00 sec)  

進行相關操作,

mysql> show databases;  +--------------------+  | Database           |  +--------------------+  | information_schema |  | mysql              |  | performance_schema |  | sys                |  | yeyz               |  +--------------------+  5 rows in set (0.00 sec)    mysql> use yeyz;  Reading table information for completion of table and column names  You can turn off this feature to get a quicker startup with -A    Database changed  mysql> show tables;  +----------------+  | Tables_in_yeyz |  +----------------+  | test_tbl0      |  +----------------+  1 row in set (0.00 sec)    mysql> select * from test_tbl0;  +------+----------+  | id   | name     |  +------+----------+  |    1 | zhangsan |  |    2 | lisi     |  |    3 | wangwu   |  +------+----------+  3 rows in set (0.00 sec)  

如果我們進行delete操作,則會報錯,因為role_ro只有select權限。

mysql> delete from yeyz.test_tbl0;  ERROR 1142 (42000): DELETE command denied to user 'yeyz_ro'@'127.0.0.1' for table 'test_tbl0'  mysql>  

這種"激活"角色的方法可以讓用戶擁有角色所擁有的權限,但是不難看出來,每次給新建用戶綁定一個角色,在新建用戶登錄之前,都得將該用戶激活一下,從操作上看不是特別方便,如何讓所有的指定的角色都即時生效呢?

MySQL提供了一個系統參數來解決這個問題,該參數是:

mysql> show variables like '%activate%';  +-----------------------------+-------+  | Variable_name               | Value |  +-----------------------------+-------+  | activate_all_roles_on_login | OFF   |  +-----------------------------+-------+  1 row in set (0.00 sec)  

該參數是默認關閉的,直接打開即可。

03

多個角色之間如何切換?

我們知道,當我們創建一個用戶的時候,可以給它綁定多個角色,那麼如何在多個角色之間進行切換,我們一把。

首先,創建賬號yeyz_ro_and_rw,並將上面的role_ro和role_rw兩個角色綁定在該用戶上,並指定role_ro為默認角色:

mysql> create user yeyz_ro_and_rw@'%' identified by 'yeyz';  Query OK, 0 rows affected (0.02 sec)    mysql> grant 'role_ro' to yeyz_ro_and_rw@'%';  Query OK, 0 rows affected (0.00 sec)    mysql> grant 'role_rw' to yeyz_ro_and_rw@'%';  Query OK, 0 rows affected (0.00 sec)      mysql> set default role 'role_ro' to yeyz_ro_and_rw@'%';  Query OK, 0 rows affected (0.00 sec)    mysql> exit  Bye  192:~ root# /usr/local/mysql_8.0/bin/mysql -uyeyz_ro_and_rw -pyeyz -h127.0.0.1 --socket=/data/mysql_5306/tmp/mysql.sock --port=5306  ...  mysql> use yeyz;  Database changed    mysql> select * from test_tbl0;  +------+----------+  | id   | name     |  +------+----------+  |    1 | zhangsan |  |    2 | lisi     |  |    3 | wangwu   |  +------+----------+  3 rows in set (0.00 sec)    mysql> insert into test_tbl0 values (4,'zhaoliu');  ERROR 1142 (42000): INSERT command denied to user 'yeyz_ro_and_rw'@'127.0.0.1' for table 'test_tbl0'  mysql>  

可以看到,role_ro擁有select的權限,所以賬號yeyz_ro_and_rw可以對yeyz數據庫下面的表test_tbl0進行select操作,但是執行insert操作的時候報錯。也容易理解,因為角色role_ro沒有insert權限。

此時將用戶的角色切換成role_rw,再次執行:

mysql> insert into test_tbl0 values (4,'zhaoliu');  ERROR 1142 (42000): INSERT command denied to user 'yeyz_ro_and_rw'@'127.0.0.1' for table 'test_tbl0'  mysql> select current_role();  +----------------+  | current_role() |  +----------------+  | `role_ro`@`%`  |  +----------------+  1 row in set (0.00 sec)    mysql> set role 'role_rw';  Query OK, 0 rows affected (0.00 sec)    mysql> insert into test_tbl0 values (4,'zhaoliu');  Query OK, 1 row affected (0.01 sec)    mysql> select current_role();  +----------------+  | current_role() |  +----------------+  | `role_rw`@`%`  |  +----------------+  1 row in set (0.00 sec)  

可以看到,再次執行insert操作的時候,執行成功了,原因是將角色切換到了role_rw,而role_rw擁有insert權限。

04

強制角色定義

強制角色,顧名思義,就是用戶賬號強制綁定的一個角色,如果我們在創建用戶的時候,想要給用戶賦予一定的權限,那麼可以通過設置一個強制角色,來給所有新生成的用戶都賦予這個角色的權限。強制角色一般是需要定義在my.cnf文件中的,假設我們要定義一個強制角色,擁有對yeyz庫的select權限,有兩種方法:

第一種是可以在配置文件中寫下:

[mysqld]  mandatory_roles='role_ro'  

這樣,所有新創建的賬號就有了該角色的權限。

第二種是運行過程中輸入下面命令:

set persist mandatory_roles = 'role_ro';

這樣,強制角色就永久生效了。

有以下幾點需要注意

1、這裡的永久生效,是指即使MySQL服務器重啟了,那麼該配置也會生效。相當於改了my.cnf配置文件,需要區別於MySQL5.7版本的set global語法。

2、強制角色也需要使用set default role的方法進行"角色激活",或者通過修改參數activate_all_roles_on_login的方法進行"激活"才可以生效。

3、強制角色不能通過revoke的方法或者drop的語法進行權限回收或者角色刪除

4、不能將包含system_user權限的角色列在強制角色列表中。

5、如果只是在配置文件中指定了角色為強制角色,但是實際上該角色不存在於mysql.user表裏面,則後續創建的賬號不會繼承該角色的權限。如果後續人工在MySQL實例中對強制角色進行了補充,則需要進行flush privileges操作以確保設置生效。