//
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操作以确保设置生效。