MySQL用户账号管理类问题

一、如何在给定场景下为用户授权

1、MySQL常用的用户权限
(1)DML权限
权限 备注
select 查询表中数据
insert 向表中插入数据
update 更新表中数据
delete 删除表中数据
execute 执行存储过程
(2)DDL权限
权限 备注
create 新建数据库、数据表
alter 修改表结构
drop 删除数据库、数据表
index 建立和删除索引
(3)Admin权限
权限 备注
create user 建立新的用户
grant option 为其他用户授权
super 管理服务器,比如设置全局变量、kill掉进程、执行change master语句等

一般来说,Admin权限只有DBA使用

(4)查看当前MySQL所有的权限列表

show privileges;

mysql> show privileges;
+----------------------------+---------------------------------------+-------------------------------------------------------+
| Privilege                  | Context                               | Comment                                               |
+----------------------------+---------------------------------------+-------------------------------------------------------+
| Alter                      | Tables                                | To alter the table                                    |
| Alter routine              | Functions,Procedures                  | To alter or drop stored functions/procedures          |
| Create                     | Databases,Tables,Indexes              | To create new databases and tables                    |
| Create routine             | Databases                             | To use CREATE FUNCTION/PROCEDURE                      |
| Create role                | Server Admin                          | To create new roles                                   |
| Create temporary tables    | Databases                             | To use CREATE TEMPORARY TABLE                         |
| Create view                | Tables                                | To create new views                                   |
| Create user                | Server Admin                          | To create new users                                   |
| Delete                     | Tables                                | To delete existing rows                               |
| Drop                       | Databases,Tables                      | To drop databases, tables, and views                  |
| Drop role                  | Server Admin                          | To drop roles                             
...
2、如何为用户授权
grant \
# 指定授予用户什么权限
select,insert,update,delete on \
# 指定这些权限可以操作哪些数据库,哪些数据表
db.tb \
# To关键字
to \
# 指定为哪个用户授权
user@ip

注:@ip如果省略,则默认为%效果,即外部任何网络均可访问。

这里还可以是@localhost、@192.168.78.% 这种指定仅本地服务器可以访问、仅指定网段可以访问。

一次只能为用户授权一个数据库的权限,如果想为用户授予多个数据库权限,则需要执行多次授权语句。这点在下面的使用实例中会体现。

3、如何收回用户权限
revoke \
# 回收的权限列表
insert,update \
# 指定收回哪些数据库、数据表的操作权限
on db.tb \
# From关键字
from \
# 指定收回哪个用户的权限
user@ip
4、使用实例
(1)5.5,5.6,5.7版本,如何为用户授权
# 创建用户
mysql> create user 'test_user'@'%' identified by '123456';
Query OK, 0 rows affected (0.00 sec)

# 为用户授予在new_retail和public数据库的所有数据表的select、update、insert权限
mysql> grant select,update,insert on new_retail.* to 'test_user';
Query OK, 0 rows affected (0.00 sec)

mysql> grant select,update,insert on public.* to 'test_user';
Query OK, 0 rows affected (0.00 sec)

#查看用户当前拥有的权限
mysql> show grants for 'test_user';
+-------------------------------------------------------------------+
| Grants for test_user@%                                            |
+-------------------------------------------------------------------+
| GRANT USAGE ON *.* TO `test_user`@`%`                             |
| GRANT SELECT, INSERT, UPDATE ON `public`.* TO `test_user`@`%`     |
| GRANT SELECT, INSERT, UPDATE ON `new_retail`.* TO `test_user`@`%` |
+-------------------------------------------------------------------+
3 rows in set (0.00 sec)
(2)8.0版本中如何为用户授权

8.0版本之前,还没有角色的概念,因此只能对单个用户逐一授权。

但8.0版本之后,新增了角色的概念,我们可以先创建角色,然后为角色分配权限,最后再给用户分配角色。

当然,我们也可以采用和之前5.7版本一样的方式,不引入角色的概念,直接为用户授权。

下面演示8.0版本中,如何使用角色,为用户授权

# 创建角色
mysql> create role 'test_role';
Query OK, 0 rows affected (0.00 sec)

# 给角色授予权限
mysql> grant select on *.* to test_role;
Query OK, 0 rows affected (0.01 sec)

# 创建用户
mysql> create user 'read_user'@'%' identified by '123456';
Query OK, 0 rows affected (0.01 sec)

# 给用户赋予角色
mysql> grant 'test_role' to 'read_user';
Query OK, 0 rows affected (0.00 sec)

# 给角色增加insert权限
mysql> grant insert on *.* to 'test_role';
Query OK, 0 rows affected (0.00 sec)

# 移除角色insert权限
mysql> revoke insert on *.* from 'test_role';
Query OK, 0 rows affected (0.01 sec)

# 查看角色与用户关系
mysql>select *from mysql.role_edges;
+-----------+-----------+---------+-----------+-------------------+
|FROM_HOST|FROM_USER|TO_HOST|TO_USER  |WITH_ADMIN_OPTION|
+-----------+-----------+---------+-----------+-------------------+
|%  |role_test |%  |read_user |N  |
+-----------+-----------+---------+-----------+-------------------+
1row inset (0.00sec)

# 查看用户当前拥有的角色
mysql> show grants for 'read_user';
+------------------------------------------------------------+
| Grants for read_user@%                                     |
+------------------------------------------------------------+
| GRANT USAGE ON *.* TO `read_user`@`%`                      |
| GRANT `insert_role`@`%`,`test_role`@`%` TO `read_user`@`%` |
+------------------------------------------------------------+

# 删除角色
mysql>drop role test_role;
QueryOK, 0rows affected (0.06sec)

二、如何加强数据库账号的安全

对于这一点,主要需要保证以下几点:

1、最小权限原则

2、密码强度策略

3、密码过期原则(指定PASSWORD EXPIRE参数)

4、限制历史密码重用原则(8.0版本专属,ASSWORD REUSE INTERVAL参数)

5、要求gitlab、github上传代码时,.env等账号配置文件不得同时上传

三、如何迁移数据库账号到新服务器

1、源数据库与目的数据库版本一致

备份mysql库,在目的实例恢复mysql库

2、源数据库与目的数据库版本不一致

当源数据库与目的数据库版本不一致时,有两种方式来备份数据库账号,分别实例演示。

(2.1)使用MySQL自带工具MySQLPump【推荐】

# 在Linux主机执行
mysqlpump -uroot -p --users --exclude-databases=sys,mysql,public,test_80,new_retail > user.sql

说明:该方式支持5.7.11之后的版本,包括8.0版本

(2.2)使用pecona-toolkit里的pt-show-grants工具获取数据库所有授权语句,然后在目的数据库中执行这些SQL。

注:centos下安装percona-toolkit

如何导出实例:
[root@v2 ~]# pt-show-grants u=root,p=123456,h=192.168.78.102,P=3307
-- Grants dumped by pt-show-grants
-- Dumped from server 192.168.78.102 via TCP/IP, MySQL 5.6.51 at 2021-08-18 05:57:28
-- Grants for 'root'@'%'
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' WITH GRANT OPTION;
-- Grants for 'root'@'localhost'
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' WITH GRANT OPTION;
GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION;
[root@v2 ~]# 

注意,pt-show-grants 当前暂不支持获取8.0版本的授权SQL,仅支持5.5,5.6,5.7版本,当然这也足够了,因为我们迁移数据库大多都是同版本迁移或升级,没有降级一说的。