MySQL 用户权限管理
本章将介绍 MySQL 的用户管理和权限控制。
用户管理
查看用户
-- 查看所有用户
SELECT User, Host, authentication_string FROM mysql.user;
-- 查看当前用户
SELECT CURRENT_USER();
-- 查看当前登录用户
SELECT USER();
创建用户
-- 基本语法
CREATE USER 'username'@'host' IDENTIFIED BY 'password';
-- 示例
-- 本地用户
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'password123';
-- 允许从任何主机连接
CREATE USER 'admin'@'%' IDENTIFIED BY 'password123';
-- 允许从特定网段连接
CREATE USER 'readonly'@'192.168.1.%' IDENTIFIED BY 'password123';
-- 使用 MySQL 8.0+ 的 caching_sha2_password 认证
CREATE USER 'user1'@'localhost'
IDENTIFIED WITH caching_sha2_password BY 'password123';
-- 使用旧的 mysql_native_password 认证
CREATE USER 'user2'@'localhost'
IDENTIFIED WITH mysql_native_password BY 'password123';
主机格式说明:
| 主机格式 | 说明 |
|---|---|
localhost | 只能本地连接 |
127.0.0.1 | 只能本地 TCP 连接 |
% | 允许任何主机 |
192.168.1.% | 允许特定网段 |
192.168.1.100 | 只允许特定 IP |
修改用户密码
-- 修改当前用户密码
ALTER USER USER() IDENTIFIED BY 'new_password';
-- 修改指定用户密码
ALTER USER 'app_user'@'localhost' IDENTIFIED BY 'new_password';
-- 使用 SET PASSWORD
SET PASSWORD FOR 'app_user'@'localhost' = 'new_password';
-- MySQL 5.7 方式
SET PASSWORD FOR 'app_user'@'localhost' = PASSWORD('new_password');
重命名用户
-- 重命名用户
RENAME USER 'old_user'@'localhost' TO 'new_user'@'localhost';
-- 同时修改主机
RENAME USER 'user'@'localhost' TO 'user'@'%';
删除用户
-- 删除用户
DROP USER 'app_user'@'localhost';
-- 删除多个用户
DROP USER 'user1'@'localhost', 'user2'@'%';
权限管理
权限类型
全局权限
| 权限 | 说明 |
|---|---|
| ALL PRIVILEGES | 所有权限 |
| CREATE | 创建数据库和表 |
| DROP | 删除数据库和表 |
| RELOAD | 执行 FLUSH 命令 |
| SHUTDOWN | 关闭服务器 |
| PROCESS | 查看进程 |
| FILE | 读写文件 |
| GRANT OPTION | 授予他人权限 |
| SUPER | 超级权限 |
数据库权限
| 权限 | 说明 |
|---|---|
| SELECT | 查询数据 |
| INSERT | 插入数据 |
| UPDATE | 更新数据 |
| DELETE | 删除数据 |
| CREATE | 创建表 |
| DROP | 删除表 |
| INDEX | 创建/删除索引 |
| ALTER | 修改表结构 |
| CREATE TEMPORARY TABLES | 创建临时表 |
| LOCK TABLES | 锁定表 |
| CREATE VIEW | 创建视图 |
| SHOW VIEW | 查看视图 |
| CREATE ROUTINE | 创建存储过程 |
| ALTER ROUTINE | 修改存储过程 |
| EXECUTE | 执行存储过程 |
| EVENT | 事件管理 |
| TRIGGER | 触发器管理 |
授予权限
-- 基本语法
GRANT 权限 ON 对象 TO '用户'@'主机';
-- 授予所有权限
GRANT ALL PRIVILEGES ON *.* TO 'admin'@'localhost' WITH GRANT OPTION;
-- 授予特定数据库的所有权限
GRANT ALL PRIVILEGES ON mydb.* TO 'app_user'@'localhost';
-- 授予特定表的权限
GRANT SELECT, INSERT, UPDATE ON mydb.users TO 'web_user'@'localhost';
-- 授予只读权限
GRANT SELECT ON mydb.* TO 'readonly'@'%';
-- 授予特定列的权限
GRANT SELECT(id, name), UPDATE(name) ON mydb.users TO 'limited_user'@'localhost';
-- 授予存储过程执行权限
GRANT EXECUTE ON PROCEDURE mydb.my_procedure TO 'user'@'localhost';
-- 创建用户同时授权
GRANT SELECT, INSERT ON mydb.* TO 'new_user'@'localhost' IDENTIFIED BY 'password';
查看权限
-- 查看当前用户权限
SHOW GRANTS;
-- 查看指定用户权限
SHOW GRANTS FOR 'app_user'@'localhost';
-- 查看特定用户的权限详情
SELECT * FROM mysql.user WHERE User='app_user' AND Host='localhost';
-- 查看数据库级别权限
SELECT * FROM mysql.db WHERE User='app_user';
-- 查看表级别权限
SELECT * FROM mysql.tables_priv WHERE User='app_user';
撤销权限
-- 撤销权限
REVOKE 权限 ON 对象 FROM '用户'@'主机';
-- 撤销所有权限
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'admin'@'localhost';
-- 撤销特定数据库的权限
REVOKE INSERT, UPDATE ON mydb.* FROM 'app_user'@'localhost';
-- 撤销特定表的权限
REVOKE DELETE ON mydb.users FROM 'web_user'@'localhost';
-- 撤销后刷新权限
FLUSH PRIVILEGES;
权限层级
MySQL 权限按层级管理:
全局权限 (*.*)
│
├── 数据库权限 (database.*)
│ │
│ └── 表权限 (database.table)
│ │
│ └── 列权限 (database.table(column))
│
└── 存储过程权限 (PROCEDURE database.procedure)
-- 全局权限
GRANT SELECT ON *.* TO 'global_user'@'localhost';
-- 数据库权限
GRANT SELECT ON mydb.* TO 'db_user'@'localhost';
-- 表权限
GRANT SELECT ON mydb.users TO 'table_user'@'localhost';
-- 列权限
GRANT SELECT(name, email) ON mydb.users TO 'column_user'@'localhost';
角色管理(MySQL 8.0+)
MySQL 8.0 引入了角色(Role)功能,方便权限管理:
创建和管理角色
-- 创建角色
CREATE ROLE 'app_read', 'app_write', 'app_admin';
-- 为角色授权
GRANT SELECT ON mydb.* TO 'app_read';
GRANT INSERT, UPDATE, DELETE ON mydb.* TO 'app_write';
GRANT ALL PRIVILEGES ON mydb.* TO 'app_admin';
-- 将角色授予用户
GRANT 'app_read' TO 'readonly_user'@'localhost';
GRANT 'app_read', 'app_write' TO 'editor_user'@'localhost';
GRANT 'app_admin' TO 'admin_user'@'localhost';
-- 查看角色权限
SHOW GRANTS FOR 'app_read';
使用角色
-- 设置默认激活的角色
SET DEFAULT ROLE ALL TO 'editor_user'@'localhost';
-- 查看当前激活的角色
SELECT CURRENT_ROLE();
-- 手动激活角色
SET ROLE 'app_read';
-- 激活所有授予的角色
SET ROLE ALL;
-- 取消激活角色
SET ROLE NONE;
删除角色
-- 删除角色
DROP ROLE 'app_read', 'app_write';
-- 从用户撤销角色
REVOKE 'app_read' FROM 'readonly_user'@'localhost';
用户管理最佳实践
1. 最小权限原则
-- 不好:授予过多权限
GRANT ALL PRIVILEGES ON *.* TO 'web_user'@'localhost';
-- 好:只授予必要权限
GRANT SELECT, INSERT, UPDATE ON webapp.* TO 'web_user'@'localhost';
2. 使用角色管理权限
-- 创建角色
CREATE ROLE 'read_only', 'read_write', 'administrator';
GRANT SELECT ON *.* TO 'read_only';
GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO 'read_write';
GRANT ALL PRIVILEGES ON *.* TO 'administrator' WITH GRANT OPTION;
-- 分配角色给用户
GRANT 'read_only' TO 'analyst1'@'%';
GRANT 'read_write' TO 'developer1'@'%';
GRANT 'administrator' TO 'dba'@'localhost';
3. 限制远程访问
-- 不推荐
CREATE USER 'user'@'%' IDENTIFIED BY 'password';
-- 推荐:限制 IP 范围
CREATE USER 'user'@'192.168.1.%' IDENTIFIED BY 'password';
CREATE USER 'user'@'10.0.0.100' IDENTIFIED BY 'password';
4. 密码策略
-- 设置密码过期
ALTER USER 'user'@'localhost' PASSWORD EXPIRE INTERVAL 90 DAY;
-- 设置密码历史(不能重复使用最近 5 个密码)
ALTER USER 'user'@'localhost' PASSWORD HISTORY 5;
-- 设置密码重用间隔
ALTER USER 'user'@'localhost' PASSWORD REUSE INTERVAL 365 DAY;
-- 设置登录失败锁定(MySQL 8.0+)
CREATE USER 'user'@'localhost'
IDENTIFIED BY 'password'
FAILED_LOGIN_ATTEMPTS 3
PASSWORD_LOCK_TIME 1;
5. 定期审计
-- 查看所有用户
SELECT User, Host, account_locked, password_expired
FROM mysql.user;
-- 查看所有权限
SELECT User, Host, Select_priv, Insert_priv, Update_priv, Delete_priv
FROM mysql.user;
-- 查看空密码用户
SELECT User, Host FROM mysql.user WHERE authentication_string = '';
-- 查看近期连接历史(需要开启审计插件)
SELECT * FROM mysql.general_log
WHERE command_type = 'Connect'
ORDER BY event_time DESC LIMIT 100;
连接安全
SSL 连接
-- 查看SSL状态
SHOW VARIABLES LIKE '%ssl%';
-- 强制用户使用 SSL
ALTER USER 'user'@'%' REQUIRE SSL;
-- 要求客户端证书
ALTER USER 'user'@'%' REQUIRE X509;
-- 指定证书
ALTER USER 'user'@'%'
REQUIRE SUBJECT '/CN=user.example.com'
AND ISSUER '/CN=CA.example.com';
连接限制
-- 限制每小时查询次数
ALTER USER 'user'@'localhost' WITH MAX_QUERIES_PER_HOUR 1000;
-- 限制每小时更新次数
ALTER USER 'user'@'localhost' WITH MAX_UPDATES_PER_HOUR 500;
-- 限制每小时连接次数
ALTER USER 'user'@'localhost' WITH MAX_CONNECTIONS_PER_HOUR 100;
-- 限制同时连接数
ALTER USER 'user'@'localhost' WITH MAX_USER_CONNECTIONS 10;
小结
本章我们学习了:
- 用户管理:创建、修改、删除用户
- 权限类型:全局、数据库、表、列权限
- 授予权限:GRANT 语句的使用
- 撤销权限:REVOKE 语句的使用
- 角色管理:MySQL 8.0 的角色功能
- 最佳实践:最小权限、密码策略、审计
练习
- 创建一个只读用户和一个读写用户
- 创建角色并分配给用户
- 设置用户的密码过期策略
- 审计当前数据库的用户权限