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