MySQL 8.0授权管理

1. 概述

1.1 MySQL 8.0授权机制的重要性

MySQL 8.0授权管理是数据库安全的核心组成部分,通过精细化的权限控制,确保只有授权的用户才能访问和操作相应的数据库资源。MySQL 8.0在授权机制上相比之前版本有了重大改进,包括角色管理、密码策略增强、认证插件优化等。

授权管理的价值

  • 数据安全:防止未授权访问和操作
  • 权限分离:实现最小权限原则
  • 合规要求:满足等保、合规审计要求
  • 运维效率:通过角色管理简化权限分配

1.2 MySQL 8.0授权新特性

相比MySQL 5.7的改进

  1. 角色管理:支持角色的创建、授予和回收
  2. 密码策略增强:更严格的密码复杂度要求
  3. 认证插件优化:默认使用caching_sha2_password
  4. 权限表优化:权限表结构优化,性能提升
  5. 动态权限:支持动态权限管理

1.3 本文内容结构

本文将从以下几个方面详细介绍MySQL 8.0授权管理:

  1. 用户管理:创建、修改、删除用户
  2. 权限授予:GRANT语句详解
  3. 权限回收:REVOKE语句详解
  4. 权限查看:查看用户权限和角色
  5. 角色管理:角色的创建和使用
  6. 密码策略:密码复杂度和管理
  7. 安全认证:认证插件和SSL连接
  8. 最佳实践:运维安全建议

2. 用户管理

2.1 创建用户

2.1.1 基本语法

1
2
3
4
5
6
7
8
CREATE USER [IF NOT EXISTS] 
'username'@'hostname'
[IDENTIFIED BY 'password']
[IDENTIFIED WITH auth_plugin]
[PASSWORD EXPIRE]
[ACCOUNT LOCK | ACCOUNT UNLOCK]
[REQUIRE SSL]
[WITH resource_option];

2.1.2 创建用户示例

基础创建

1
2
-- 创建用户(MySQL 8.0默认使用caching_sha2_password)
CREATE USER 'dba'@'%' IDENTIFIED BY 'qwe@123';

指定认证插件

1
2
3
4
5
-- 使用mysql_native_password插件(兼容旧版本)
CREATE USER 'dba'@'%' IDENTIFIED WITH mysql_native_password BY 'qwe@123';

-- 使用caching_sha2_password插件(MySQL 8.0默认)
CREATE USER 'dba'@'%' IDENTIFIED WITH caching_sha2_password BY 'qwe@123';

创建用户并设置密码策略

1
2
3
4
5
6
7
8
9
10
11
-- 创建用户,密码立即过期
CREATE USER 'dba'@'%' IDENTIFIED BY 'qwe@123' PASSWORD EXPIRE;

-- 创建用户,密码90天后过期
CREATE USER 'dba'@'%' IDENTIFIED BY 'qwe@123' PASSWORD EXPIRE INTERVAL 90 DAY;

-- 创建用户,账户锁定
CREATE USER 'dba'@'%' IDENTIFIED BY 'qwe@123' ACCOUNT LOCK;

-- 创建用户,要求SSL连接
CREATE USER 'dba'@'%' IDENTIFIED BY 'qwe@123' REQUIRE SSL;

创建用户并设置资源限制

1
2
3
4
5
6
7
-- 创建用户,设置资源限制
CREATE USER 'dba'@'%' IDENTIFIED BY 'qwe@123'
WITH
MAX_QUERIES_PER_HOUR 1000
MAX_UPDATES_PER_HOUR 500
MAX_CONNECTIONS_PER_HOUR 100
MAX_USER_CONNECTIONS 10;

资源限制说明

  • MAX_QUERIES_PER_HOUR:每小时最大查询数
  • MAX_UPDATES_PER_HOUR:每小时最大更新数
  • MAX_CONNECTIONS_PER_HOUR:每小时最大连接数
  • MAX_USER_CONNECTIONS:最大并发连接数

2.1.3 创建用户最佳实践

1
2
3
4
5
6
7
8
-- 推荐的用户创建方式
CREATE USER 'dba'@'%'
IDENTIFIED WITH caching_sha2_password BY 'StrongPassword123!@#'
PASSWORD EXPIRE INTERVAL 90 DAY
REQUIRE SSL
WITH
MAX_QUERIES_PER_HOUR 10000
MAX_CONNECTIONS_PER_HOUR 1000;

最佳实践要点

  • 使用强密码
  • 设置密码过期策略
  • 要求SSL连接(生产环境)
  • 设置合理的资源限制
  • 使用合适的认证插件

2.2 修改用户

2.2.1 修改用户密码

1
2
3
4
5
-- 修改用户密码
ALTER USER 'dba'@'%' IDENTIFIED BY 'NewPassword123!@#';

-- 修改用户密码并指定认证插件
ALTER USER 'dba'@'%' IDENTIFIED WITH mysql_native_password BY 'NewPassword123!@#';

2.2.2 修改用户属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- 修改密码过期策略
ALTER USER 'dba'@'%' PASSWORD EXPIRE INTERVAL 90 DAY;

-- 立即过期密码
ALTER USER 'dba'@'%' PASSWORD EXPIRE;

-- 账户锁定/解锁
ALTER USER 'dba'@'%' ACCOUNT LOCK;
ALTER USER 'dba'@'%' ACCOUNT UNLOCK;

-- 要求SSL连接
ALTER USER 'dba'@'%' REQUIRE SSL;

-- 修改资源限制
ALTER USER 'dba'@'%'
WITH MAX_QUERIES_PER_HOUR 2000;

2.2.3 重命名用户

1
2
-- 重命名用户
RENAME USER 'dba'@'%' TO 'dba_admin'@'%';

2.3 删除用户

1
2
3
4
5
6
7
8
-- 删除用户
DROP USER 'dba'@'%';

-- 如果用户不存在也不报错
DROP USER IF EXISTS 'dba'@'%';

-- 删除多个用户
DROP USER 'dba'@'%', 'appuser'@'localhost';

注意事项

  • 删除用户会同时删除该用户的所有权限
  • 删除前确认无业务依赖
  • 建议先锁定账户,观察后再删除

2.4 查看用户

2.4.1 查看所有用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- 查看所有用户
SELECT user, host, plugin, authentication_string
FROM mysql.user;

-- 查看用户详细信息
SELECT
user,
host,
plugin,
password_expired,
password_last_changed,
password_lifetime,
account_locked,
password_require_current
FROM mysql.user;

2.4.2 查看用户创建语句

1
2
-- 查看用户创建语句(MySQL 8.0新特性)
SHOW CREATE USER 'dba'@'%';

输出示例

1
2
3
4
5
CREATE USER 'dba'@'%' IDENTIFIED WITH 'caching_sha2_password' AS '$A$005$...' 
REQUIRE SSL PASSWORD EXPIRE INTERVAL 90 DAY
ACCOUNT UNLOCK PASSWORD HISTORY DEFAULT
PASSWORD REUSE INTERVAL DEFAULT
PASSWORD REQUIRE CURRENT DEFAULT;

3. 权限授予(GRANT)

3.1 GRANT语法

3.1.1 基本语法

1
2
3
4
5
6
GRANT privilege_type [(column_list)]
[, privilege_type [(column_list)]] ...
ON [object_type] privilege_level
TO user [auth_option] [, user [auth_option]] ...
[WITH GRANT OPTION]
[AS user [WITH ROLE role]];

3.1.2 权限级别

全局权限

1
2
-- 授予所有数据库的所有权限
GRANT ALL PRIVILEGES ON *.* TO 'dba'@'%' WITH GRANT OPTION;

数据库权限

1
2
3
4
5
6
-- 授予testdb数据库的所有权限
GRANT ALL PRIVILEGES ON testdb.* TO 'dba'@'%';

-- 授予多个数据库的权限
GRANT SELECT, INSERT ON testdb.* TO 'appuser'@'%';
GRANT SELECT ON prod_db.* TO 'readonly'@'%';

表权限

1
2
3
4
5
-- 授予testdb.users表的所有权限
GRANT ALL PRIVILEGES ON testdb.users TO 'dba'@'%';

-- 授予特定表的特定权限
GRANT SELECT, INSERT, UPDATE ON testdb.users TO 'appuser'@'%';

列权限

1
2
-- 授予特定列的权限
GRANT SELECT (id, name), UPDATE (name) ON testdb.users TO 'appuser'@'%';

存储过程和函数权限

1
2
3
4
5
-- 授予存储过程执行权限
GRANT EXECUTE ON PROCEDURE testdb.get_user TO 'appuser'@'%';

-- 授予函数执行权限
GRANT EXECUTE ON FUNCTION testdb.calculate_total TO 'appuser'@'%';

3.2 常用权限类型

3.2.1 数据权限

权限 说明 级别
SELECT 查询数据 全局/数据库/表/列
INSERT 插入数据 全局/数据库/表/列
UPDATE 更新数据 全局/数据库/表/列
DELETE 删除数据 全局/数据库/表
CREATE 创建数据库/表 全局/数据库
DROP 删除数据库/表 全局/数据库
ALTER 修改表结构 全局/数据库/表
INDEX 创建/删除索引 全局/数据库/表

3.2.2 管理权限

权限 说明 级别
GRANT OPTION 授予权限给其他用户 全局/数据库/表
SUPER 超级权限 全局
PROCESS 查看所有进程 全局
RELOAD 重新加载配置 全局
SHUTDOWN 关闭服务器 全局
FILE 读写文件 全局
REPLICATION SLAVE 复制从库权限 全局
REPLICATION CLIENT 复制客户端权限 全局

3.3 权限授予示例

3.3.1 DBA权限

1
2
3
4
-- 创建DBA用户并授予所有权限
CREATE USER 'dba'@'%' IDENTIFIED BY 'qwe@123';
GRANT ALL PRIVILEGES ON *.* TO 'dba'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;

3.3.2 应用用户权限

1
2
3
4
-- 创建应用用户,授予特定数据库的读写权限
CREATE USER 'appuser'@'%' IDENTIFIED BY 'AppPass123!';
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'appuser'@'%';
FLUSH PRIVILEGES;

3.3.3 只读用户权限

1
2
3
4
-- 创建只读用户
CREATE USER 'readonly'@'%' IDENTIFIED BY 'ReadOnly123!';
GRANT SELECT ON *.* TO 'readonly'@'%';
FLUSH PRIVILEGES;

3.3.4 备份用户权限

1
2
3
4
-- 创建备份用户
CREATE USER 'backup'@'localhost' IDENTIFIED BY 'Backup123!';
GRANT SELECT, RELOAD, LOCK TABLES, REPLICATION CLIENT, PROCESS ON *.* TO 'backup'@'localhost';
FLUSH PRIVILEGES;

3.3.5 监控用户权限

1
2
3
4
5
-- 创建监控用户
CREATE USER 'monitor'@'%' IDENTIFIED BY 'Monitor123!';
GRANT PROCESS, REPLICATION CLIENT, SELECT ON performance_schema.* TO 'monitor'@'%';
GRANT SELECT ON sys.* TO 'monitor'@'%';
FLUSH PRIVILEGES;

3.4 WITH GRANT OPTION

1
2
-- 授予权限并允许该用户授予权限给其他用户
GRANT ALL PRIVILEGES ON testdb.* TO 'dba'@'%' WITH GRANT OPTION;

WITH GRANT OPTION说明

  • 允许用户将自己拥有的权限授予其他用户
  • 通常只授予给管理员用户
  • 需要谨慎使用,避免权限扩散

3.5 权限生效

1
2
-- 刷新权限表,使权限立即生效
FLUSH PRIVILEGES;

FLUSH PRIVILEGES说明

  • 使用GRANTREVOKECREATE USER等语句后,权限会自动生效
  • 直接修改mysql.user表后需要执行FLUSH PRIVILEGES
  • 建议在权限操作后执行,确保权限立即生效

4. 权限回收(REVOKE)

4.1 REVOKE语法

4.1.1 基本语法

1
2
3
4
5
6
7
REVOKE privilege_type [(column_list)]
[, privilege_type [(column_list)]] ...
ON [object_type] privilege_level
FROM user [, user] ...;

-- 回收GRANT OPTION
REVOKE GRANT OPTION ON privilege_level FROM user;

4.1.2 权限回收示例

回收所有权限

1
2
3
-- 回收所有权限
REVOKE ALL PRIVILEGES ON *.* FROM 'dba'@'%';
FLUSH PRIVILEGES;

回收特定权限

1
2
3
4
5
6
7
8
9
-- 回收特定数据库的权限
REVOKE ALL PRIVILEGES ON testdb.* FROM 'appuser'@'%';

-- 回收特定表的权限
REVOKE SELECT, INSERT ON testdb.users FROM 'appuser'@'%';

-- 回收特定权限
REVOKE DELETE ON testdb.* FROM 'appuser'@'%';
FLUSH PRIVILEGES;

回收GRANT OPTION

1
2
3
-- 回收授予权限的能力
REVOKE GRANT OPTION ON *.* FROM 'dba'@'%';
FLUSH PRIVILEGES;

4.2 权限回收注意事项

  1. 权限级联:回收权限时,如果用户通过WITH GRANT OPTION授予了其他用户权限,需要先回收这些权限
  2. 权限检查:回收权限前先查看用户当前权限
  3. 业务影响:回收权限可能影响业务,需要谨慎操作
  4. 立即生效:使用REVOKE后权限立即生效,建议执行FLUSH PRIVILEGES

5. 权限查看

5.1 查看用户权限

5.1.1 SHOW GRANTS

1
2
3
4
5
-- 查看当前用户权限
SHOW GRANTS;

-- 查看指定用户权限
SHOW GRANTS FOR 'dba'@'%';

输出示例

1
2
3
4
5
6
+---------------------------------------------------+
| Grants for dba@% |
+---------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO `dba`@`%` |
| WITH GRANT OPTION |
+---------------------------------------------------+

5.1.2 查看用户创建语句

1
2
-- 查看用户创建语句(MySQL 8.0)
SHOW CREATE USER 'dba'@'%';

输出示例

1
2
3
4
5
6
7
8
9
+------------------------------------------------------------------+
| CREATE USER for dba@% |
+------------------------------------------------------------------+
| CREATE USER 'dba'@'%' IDENTIFIED WITH 'caching_sha2_password' |
| AS '$A$005$...' REQUIRE SSL PASSWORD EXPIRE INTERVAL 90 DAY |
| ACCOUNT UNLOCK PASSWORD HISTORY DEFAULT |
| PASSWORD REUSE INTERVAL DEFAULT |
| PASSWORD REQUIRE CURRENT DEFAULT |
+------------------------------------------------------------------+

5.2 查询权限表

5.2.1 查看用户表

1
2
3
4
-- 查看所有用户
SELECT user, host, plugin, authentication_string
FROM mysql.user
WHERE user = 'dba';

5.2.2 查看全局权限

1
2
-- 查看用户全局权限
SELECT * FROM mysql.user WHERE user = 'dba' AND host = '%';

5.2.3 查看数据库权限

1
2
-- 查看用户数据库权限
SELECT * FROM mysql.db WHERE user = 'dba' AND host = '%';

5.2.4 查看表权限

1
2
-- 查看用户表权限
SELECT * FROM mysql.tables_priv WHERE user = 'dba' AND host = '%';

5.2.5 查看列权限

1
2
-- 查看用户列权限
SELECT * FROM mysql.columns_priv WHERE user = 'dba' AND host = '%';

5.3 权限查询脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
-- 查看用户所有权限的完整脚本
SELECT
CONCAT('用户: ', user, '@', host) AS user_info,
CONCAT('认证插件: ', plugin) AS auth_plugin,
CONCAT('账户锁定: ', IF(account_locked = 'Y', '是', '否')) AS account_status,
CONCAT('密码过期: ', IF(password_expired = 'Y', '是', '否')) AS password_status
FROM mysql.user
WHERE user = 'dba' AND host = '%';

-- 查看用户权限详情
SELECT
'全局权限' AS privilege_level,
CONCAT(user, '@', host) AS user_host,
CASE
WHEN Select_priv = 'Y' THEN 'SELECT '
ELSE ''
END ||
CASE
WHEN Insert_priv = 'Y' THEN 'INSERT '
ELSE ''
END ||
CASE
WHEN Update_priv = 'Y' THEN 'UPDATE '
ELSE ''
END ||
CASE
WHEN Delete_priv = 'Y' THEN 'DELETE '
ELSE ''
END AS privileges
FROM mysql.user
WHERE user = 'dba' AND host = '%';

6. 角色管理(MySQL 8.0新特性)

6.1 角色概述

角色(Role)是MySQL 8.0引入的新特性,可以将一组权限打包成角色,然后授予给用户,简化权限管理。

角色的优势

  • 简化管理:一次定义,多处使用
  • 权限分组:按职能组织权限
  • 易于维护:修改角色权限,所有用户自动更新
  • 符合规范:符合RBAC(基于角色的访问控制)模型

6.2 创建角色

1
2
3
4
5
-- 创建角色
CREATE ROLE 'app_read', 'app_write', 'app_admin';

-- 创建角色并指定主机
CREATE ROLE 'dba'@'localhost', 'readonly'@'%';

6.3 授予角色权限

1
2
3
4
-- 授予角色权限
GRANT SELECT ON appdb.* TO 'app_read';
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'app_write';
GRANT ALL PRIVILEGES ON appdb.* TO 'app_admin';

6.4 授予角色给用户

1
2
3
4
5
6
7
-- 授予角色给用户
GRANT 'app_read' TO 'appuser1'@'%';
GRANT 'app_write' TO 'appuser2'@'%';
GRANT 'app_admin' TO 'dba'@'%';

-- 授予多个角色
GRANT 'app_read', 'app_write' TO 'appuser3'@'%';

6.5 激活角色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- 查看当前用户角色
SELECT CURRENT_ROLE();

-- 激活角色(会话级别)
SET ROLE 'app_read';

-- 激活所有角色
SET ROLE ALL;

-- 激活默认角色(永久)
ALTER USER 'appuser1'@'%' DEFAULT ROLE 'app_read';

-- 激活所有默认角色
ALTER USER 'appuser1'@'%' DEFAULT ROLE ALL;

角色激活说明

  • 角色授予后不会自动激活
  • 需要显式激活角色才能使用权限
  • 可以设置默认角色,用户登录时自动激活

6.6 查看角色

1
2
3
4
5
6
7
8
-- 查看所有角色
SELECT * FROM mysql.roles_mapping;

-- 查看用户角色
SHOW GRANTS FOR 'appuser1'@'%' USING 'app_read';

-- 查看角色权限
SHOW GRANTS FOR 'app_read';

6.7 回收角色

1
2
3
4
5
-- 从用户回收角色
REVOKE 'app_read' FROM 'appuser1'@'%';

-- 回收角色权限
REVOKE SELECT ON appdb.* FROM 'app_read';

6.8 删除角色

1
2
-- 删除角色
DROP ROLE 'app_read';

注意事项

  • 删除角色前需要先从所有用户回收
  • 删除角色不会影响已授予的权限

6.9 角色管理最佳实践

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- 1. 创建标准角色
CREATE ROLE 'db_readonly', 'db_readwrite', 'db_admin';

-- 2. 授予角色权限
GRANT SELECT ON *.* TO 'db_readonly';
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'db_readwrite';
GRANT ALL PRIVILEGES ON appdb.* TO 'db_admin';

-- 3. 授予角色给用户并设置默认角色
CREATE USER 'appuser'@'%' IDENTIFIED BY 'Password123!';
GRANT 'db_readwrite' TO 'appuser'@'%';
ALTER USER 'appuser'@'%' DEFAULT ROLE 'db_readwrite';

-- 4. 验证角色权限
SHOW GRANTS FOR 'appuser'@'%' USING 'db_readwrite';

7. 密码策略

7.1 密码验证组件

MySQL 8.0使用validate_password组件来验证密码强度。

7.1.1 安装密码验证组件

1
2
3
4
5
6
7
8
-- 检查组件是否安装
SELECT * FROM mysql.component WHERE component = 'validate_password';

-- 安装组件
INSTALL COMPONENT 'file://component_validate_password';

-- 查看组件状态
SHOW VARIABLES LIKE 'validate_password%';

7.1.2 密码策略配置

1
2
-- 查看密码策略配置
SHOW VARIABLES LIKE 'validate_password%';

输出示例

1
2
3
4
5
6
7
8
9
10
11
+--------------------------------------+--------+
| Variable_name | Value |
+--------------------------------------+--------+
| validate_password.check_user_name | ON |
| validate_password.dictionary_file | |
| validate_password.length | 8 |
| validate_password.mixed_case_count | 1 |
| validate_password.number_count | 1 |
| validate_password.policy | MEDIUM |
| validate_password.special_char_count | 1 |
+--------------------------------------+--------+

参数说明

参数 说明 推荐值
validate_password.length 密码最小长度 8+
validate_password.policy 密码策略(LOW/MEDIUM/STRONG) MEDIUM/STRONG
validate_password.mixed_case_count 大小写字母数量 1+
validate_password.number_count 数字数量 1+
validate_password.special_char_count 特殊字符数量 1+
validate_password.check_user_name 检查密码是否包含用户名 ON
validate_password.dictionary_file 字典文件路径 -

7.1.3 配置密码策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- 设置密码最小长度
SET GLOBAL validate_password.length = 12;

-- 设置密码策略
SET GLOBAL validate_password.policy = STRONG;

-- 设置大小写字母数量
SET GLOBAL validate_password.mixed_case_count = 2;

-- 设置数字数量
SET GLOBAL validate_password.number_count = 2;

-- 设置特殊字符数量
SET GLOBAL validate_password.special_char_count = 2;

-- 检查密码是否包含用户名
SET GLOBAL validate_password.check_user_name = ON;

永久配置

1
2
3
4
5
6
7
8
9
# 编辑my.cnf
[mysqld]
plugin-load-add=validate_password.so
validate_password.length=12
validate_password.policy=STRONG
validate_password.mixed_case_count=2
validate_password.number_count=2
validate_password.special_char_count=2
validate_password.check_user_name=ON

7.2 密码过期策略

7.2.1 全局密码过期策略

1
2
3
4
5
6
7
8
-- 查看全局密码过期策略
SHOW VARIABLES LIKE 'default_password_lifetime';

-- 设置全局密码有效期(天)
SET GLOBAL default_password_lifetime = 90;

-- 设置为永不过期
SET GLOBAL default_password_lifetime = 0;

7.2.2 用户密码过期策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
-- 创建用户时设置密码过期
CREATE USER 'dba'@'%' IDENTIFIED BY 'Password123!'
PASSWORD EXPIRE INTERVAL 90 DAY;

-- 修改用户密码过期策略
ALTER USER 'dba'@'%' PASSWORD EXPIRE INTERVAL 90 DAY;

-- 立即过期密码
ALTER USER 'dba'@'%' PASSWORD EXPIRE;

-- 查看用户密码信息
SELECT
user,
host,
password_last_changed,
password_expired,
password_lifetime
FROM mysql.user
WHERE user = 'dba';

7.3 密码历史策略

1
2
3
4
5
6
7
8
9
10
11
12
13
-- 查看密码历史配置
SHOW VARIABLES LIKE 'password_history%';
SHOW VARIABLES LIKE 'password_reuse_interval%';

-- 设置密码历史数量(不能重复使用最近N个密码)
SET GLOBAL password_history = 5;

-- 设置密码重用间隔(天)
SET GLOBAL password_reuse_interval = 365;

-- 用户级别设置
ALTER USER 'dba'@'%' PASSWORD HISTORY 5;
ALTER USER 'dba'@'%' PASSWORD REUSE INTERVAL 365 DAY;

7.4 密码验证要求

1
2
3
4
5
-- 设置修改密码时需要提供当前密码
SET GLOBAL password_require_current = ON;

-- 用户级别设置
ALTER USER 'dba'@'%' PASSWORD REQUIRE CURRENT;

8. 安全认证

8.1 认证插件

MySQL 8.0支持多种认证插件:

8.1.1 认证插件类型

插件 说明 安全性 兼容性
caching_sha2_password MySQL 8.0默认,SHA256加密 MySQL 8.0+
sha256_password SHA256加密 MySQL 5.6+
mysql_native_password MySQL原生加密 所有版本

8.1.2 设置认证插件

1
2
3
4
5
-- 创建用户时指定认证插件
CREATE USER 'dba'@'%' IDENTIFIED WITH caching_sha2_password BY 'Password123!';

-- 修改用户认证插件
ALTER USER 'dba'@'%' IDENTIFIED WITH mysql_native_password BY 'Password123!';

8.1.3 查看认证插件

1
2
3
4
5
-- 查看用户认证插件
SELECT user, host, plugin FROM mysql.user WHERE user = 'dba';

-- 查看支持的认证插件
SELECT * FROM mysql.plugin WHERE name LIKE '%password%';

8.2 SSL连接

8.2.1 检查SSL支持

1
2
3
4
5
-- 查看SSL支持
SHOW VARIABLES LIKE '%ssl%';

-- 查看SSL状态
SHOW STATUS LIKE 'Ssl%';

8.2.2 要求SSL连接

1
2
3
4
5
6
7
8
9
10
11
-- 创建用户时要求SSL
CREATE USER 'dba'@'%' IDENTIFIED BY 'Password123!' REQUIRE SSL;

-- 修改用户要求SSL
ALTER USER 'dba'@'%' REQUIRE SSL;

-- 要求SSL并指定证书
ALTER USER 'dba'@'%'
REQUIRE SSL
REQUIRE ISSUER '/C=US/ST=CA/L=San Francisco/O=MySQL/CN=CA'
REQUIRE SUBJECT '/C=US/ST=CA/L=San Francisco/O=MySQL/CN=client';

8.2.3 验证SSL连接

1
2
3
4
5
-- 查看当前连接SSL状态
STATUS;

-- 或
SHOW STATUS LIKE 'Ssl_cipher';

输出示例

1
SSL: Cipher in use is DHE-RSA-AES256-SHA

9. 权限管理最佳实践

9.1 最小权限原则

1
2
3
4
5
6
7
8
9
10
11
-- 1. 为应用创建专用用户,只授予必要权限
CREATE USER 'appuser'@'%' IDENTIFIED BY 'StrongPassword123!';
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'appuser'@'%';

-- 2. 为只读查询创建只读用户
CREATE USER 'readonly'@'%' IDENTIFIED BY 'ReadOnly123!';
GRANT SELECT ON appdb.* TO 'readonly'@'%';

-- 3. 为备份创建专用用户
CREATE USER 'backup'@'localhost' IDENTIFIED BY 'Backup123!';
GRANT SELECT, RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'backup'@'localhost';

9.2 使用角色管理权限

1
2
3
4
5
6
7
8
9
10
11
12
-- 1. 创建标准角色
CREATE ROLE 'db_readonly', 'db_readwrite', 'db_admin';

-- 2. 授予角色权限
GRANT SELECT ON *.* TO 'db_readonly';
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'db_readwrite';
GRANT ALL PRIVILEGES ON appdb.* TO 'db_admin';

-- 3. 授予角色给用户
CREATE USER 'appuser'@'%' IDENTIFIED BY 'Password123!';
GRANT 'db_readwrite' TO 'appuser'@'%';
ALTER USER 'appuser'@'%' DEFAULT ROLE 'db_readwrite';

9.3 密码安全策略

1
2
3
4
5
6
7
8
9
10
11
12
13
-- 1. 配置强密码策略
SET GLOBAL validate_password.length = 12;
SET GLOBAL validate_password.policy = STRONG;
SET GLOBAL validate_password.mixed_case_count = 2;
SET GLOBAL validate_password.number_count = 2;
SET GLOBAL validate_password.special_char_count = 2;

-- 2. 设置密码过期策略
SET GLOBAL default_password_lifetime = 90;

-- 3. 设置密码历史
SET GLOBAL password_history = 5;
SET GLOBAL password_reuse_interval = 365;

9.4 账户安全

1
2
3
4
5
6
7
8
9
10
11
12
-- 1. 定期检查账户状态
SELECT user, host, account_locked, password_expired
FROM mysql.user;

-- 2. 锁定不使用的账户
ALTER USER 'olduser'@'%' ACCOUNT LOCK;

-- 3. 删除多余账户
DROP USER IF EXISTS 'unused_user'@'%';

-- 4. 重命名默认账户
RENAME USER 'root'@'localhost' TO 'admin'@'localhost';

9.5 权限审计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- 1. 定期查看用户权限
SELECT user, host,
CASE WHEN Select_priv = 'Y' THEN 'SELECT ' ELSE '' END ||
CASE WHEN Insert_priv = 'Y' THEN 'INSERT ' ELSE '' END ||
CASE WHEN Update_priv = 'Y' THEN 'UPDATE ' ELSE '' END ||
CASE WHEN Delete_priv = 'Y' THEN 'DELETE ' ELSE '' END AS privileges
FROM mysql.user;

-- 2. 查看用户角色
SELECT user, host, default_role
FROM mysql.user
WHERE default_role IS NOT NULL;

-- 3. 记录权限变更(建议使用审计插件)

9.6 运维脚本

9.6.1 用户权限检查脚本

1
2
3
4
5
6
7
8
9
-- 检查所有用户权限
SELECT
CONCAT(user, '@', host) AS user_host,
plugin AS auth_plugin,
IF(account_locked = 'Y', '锁定', '正常') AS account_status,
IF(password_expired = 'Y', '已过期', '正常') AS password_status,
IFNULL(password_lifetime, '永不过期') AS password_lifetime
FROM mysql.user
ORDER BY user, host;

9.6.2 权限导出脚本

1
2
3
4
5
6
7
8
-- 导出用户创建语句
SELECT CONCAT('CREATE USER ', QUOTE(user), '@', QUOTE(host),
' IDENTIFIED WITH ', QUOTE(plugin),
IF(password_expired = 'Y', ' PASSWORD EXPIRE', ''),
IF(account_locked = 'Y', ' ACCOUNT LOCK', ' ACCOUNT UNLOCK'),
';') AS create_user_sql
FROM mysql.user
WHERE user NOT IN ('mysql.sys', 'mysql.session', 'mysql.infoschema');

10. 常见问题与解决方案

10.1 权限不生效

问题:授予权限后,用户仍然无法访问

解决方案

1
2
3
4
5
6
7
8
9
-- 1. 刷新权限表
FLUSH PRIVILEGES;

-- 2. 检查用户是否激活角色
SELECT CURRENT_ROLE();
SET ROLE ALL;

-- 3. 检查权限是否正确授予
SHOW GRANTS FOR 'user'@'host';

10.2 密码策略不满足

问题:创建用户时提示密码不符合策略

解决方案

1
2
3
4
5
6
7
8
-- 1. 查看密码策略
SHOW VARIABLES LIKE 'validate_password%';

-- 2. 调整密码策略(临时)
SET GLOBAL validate_password.policy = LOW;

-- 3. 使用符合策略的强密码
CREATE USER 'dba'@'%' IDENTIFIED BY 'StrongPassword123!@#';

10.3 认证插件不兼容

问题:MySQL 8.0客户端无法连接使用caching_sha2_password的用户

解决方案

1
2
3
4
-- 1. 修改用户认证插件
ALTER USER 'dba'@'%' IDENTIFIED WITH mysql_native_password BY 'Password123!';

-- 2. 或升级客户端到支持caching_sha2_password的版本

10.4 角色权限不生效

问题:授予角色后,用户仍然没有权限

解决方案

1
2
3
4
5
6
7
8
-- 1. 激活角色
SET ROLE 'role_name';

-- 2. 设置默认角色
ALTER USER 'user'@'%' DEFAULT ROLE 'role_name';

-- 3. 检查角色权限
SHOW GRANTS FOR 'user'@'%' USING 'role_name';

10.5 权限回收后仍有权限

问题:回收权限后,用户仍然可以访问

解决方案

1
2
3
4
5
6
7
8
9
-- 1. 检查是否有多个权限来源(直接权限+角色权限)
SHOW GRANTS FOR 'user'@'%';

-- 2. 回收所有相关权限
REVOKE ALL PRIVILEGES ON *.* FROM 'user'@'%';
REVOKE 'role_name' FROM 'user'@'%';

-- 3. 刷新权限
FLUSH PRIVILEGES;

11. 运维检查清单

11.1 用户管理检查

  • 所有用户都有强密码
  • 不存在空密码用户
  • 默认账户已重命名或使用强密码
  • 多余账户已删除或锁定
  • 用户密码定期更换

11.2 权限管理检查

  • 遵循最小权限原则
  • 使用角色管理权限
  • 定期审计用户权限
  • 回收不必要的权限
  • 限制WITH GRANT OPTION的使用

11.3 安全策略检查

  • 密码策略已配置
  • 密码过期策略已设置
  • 密码历史策略已配置
  • SSL连接已启用(生产环境)
  • 账户锁定策略已配置

11.4 审计检查

  • 记录权限变更
  • 定期检查用户权限
  • 监控异常访问
  • 保留权限变更日志

12. 总结

12.1 核心要点

  1. 用户管理:创建、修改、删除用户是权限管理的基础
  2. 权限授予:使用GRANT精确控制用户权限
  3. 权限回收:使用REVOKE及时回收不必要权限
  4. 角色管理:使用角色简化权限管理
  5. 安全策略:配置密码策略和安全认证

12.2 MySQL 8.0新特性

  1. 角色管理:支持RBAC模型,简化权限管理
  2. 密码策略增强:更严格的密码复杂度要求
  3. 认证插件优化:默认使用更安全的认证方式
  4. SHOW CREATE USER:方便查看用户创建语句

12.3 架构师建议

  1. 设计阶段

    • 规划用户和角色结构
    • 设计权限分级体系
    • 制定密码安全策略
  2. 实施阶段

    • 遵循最小权限原则
    • 使用角色管理权限
    • 配置强密码策略
  3. 运维阶段

    • 定期审计用户权限
    • 监控异常访问
    • 及时回收不必要权限

12.4 最佳实践

  1. 最小权限原则:只授予必要的权限
  2. 角色管理:使用角色简化权限管理
  3. 密码安全:配置强密码策略和过期策略
  4. 定期审计:定期检查用户权限和账户状态
  5. 安全认证:生产环境使用SSL连接

相关文章