MySQL 用户权限管理完全指南

目录

1. 用户管理基础

1.1 创建新用户

基本语法:

CREATE USER 'username'@'host' IDENTIFIED BY 'password';

参数说明:

  • username: 用户名
  • host: 允许连接的主机,% 表示任意主机
  • password: 用户密码

示例:

-- 创建本地用户
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'StrongPassword123!';

-- 创建允许远程连接的用户
CREATE USER 'remote_user'@'%' IDENTIFIED BY 'AnotherStrongPass456!';

-- 创建只允许特定IP连接的用户
CREATE USER 'report_user'@'192.168.1.100' IDENTIFIED BY 'ReportPass789!';

-- 使用密码过期策略
CREATE USER 'temp_user'@'%' 
IDENTIFIED BY 'TempPass123!' 
PASSWORD EXPIRE INTERVAL 30 DAY;

-- 使用加密密码
CREATE USER 'secure_user'@'localhost' 
IDENTIFIED BY PASSWORD '*A4B6157319038724E3560894F7F932C8886EBFCF';

1.2 删除用户

语法:

DROP USER 'username'@'host';

示例:

-- 删除单个用户
DROP USER 'old_user'@'localhost';

-- 删除多个用户
DROP USER 'user1'@'%', 'user2'@'192.168.1.%';

1.3 修改用户密码

MySQL 5.7及以上版本:

ALTER USER 'username'@'host' IDENTIFIED BY 'new_password';

MySQL 5.6及以下版本:

SET PASSWORD FOR 'username'@'host' = PASSWORD('new_password');

示例:

-- 修改用户密码
ALTER USER 'app_user'@'localhost' IDENTIFIED BY 'NewStrongPass789!';

-- 设置密码永不过期
ALTER USER 'admin_user'@'localhost' 
IDENTIFIED BY 'AdminPass123!' 
PASSWORD EXPIRE NEVER;

-- 设置密码立即过期(下次登录需修改)
ALTER USER 'temp_user'@'%' PASSWORD EXPIRE;

1.4 重命名用户

语法:

RENAME USER 'old_username'@'old_host' TO 'new_username'@'new_host';

示例:

-- 重命名用户
RENAME USER 'test_user'@'localhost' TO 'dev_user'@'localhost';

-- 同时修改用户名和主机
RENAME USER 'app_user'@'%' TO 'app_user'@'192.168.1.%';

2. 权限管理详解

2.1 权限类型

数据操作权限:

  • SELECT: 查询数据
  • INSERT: 插入数据
  • UPDATE: 更新数据
  • DELETE: 删除数据
  • EXECUTE: 执行存储过程/函数

结构操作权限:

  • CREATE: 创建数据库/表/索引等
  • DROP: 删除数据库/表/索引等
  • ALTER: 修改表结构
  • INDEX: 创建/删除索引
  • CREATE VIEW: 创建视图
  • SHOW VIEW: 查看视图定义

管理权限:

  • CREATE USER: 创建用户
  • DROP USER: 删除用户
  • RELOAD: 重载权限
  • SHUTDOWN: 关闭服务器
  • SUPER: 超级权限
  • GRANT OPTION: 授予权限给其他用户

2.2 权限级别

  1. 全局级别 - 影响所有数据库
  2. 数据库级别 - 影响特定数据库
  3. 表级别 - 影响特定表
  4. 列级别 - 影响表中的特定列
  5. 子程序级别 - 影响存储过程和函数

3. 权限授予操作

3.1 授予数据库级别权限

语法:

GRANT privileges ON database_name.* TO 'username'@'host';

示例:

-- 授予数据库所有权限
GRANT ALL PRIVILEGES ON my_database.* TO 'app_user'@'localhost';

-- 授予特定权限
GRANT SELECT, INSERT, UPDATE ON sales_db.* TO 'sales_user'@'%';

-- 授予创建视图权限
GRANT CREATE VIEW, SHOW VIEW ON report_db.* TO 'report_user'@'192.168.1.%';

-- 授予权限管理权限
GRANT SELECT, INSERT ON app_db.* TO 'dev_user'@'localhost' WITH GRANT OPTION;

3.2 授予表级别权限

语法:

GRANT privileges ON database_name.table_name TO 'username'@'host';

示例:

-- 授予表的所有权限
GRANT ALL PRIVILEGES ON customers_db.users TO 'admin_user'@'localhost';

-- 授予特定表的查询权限
GRANT SELECT ON sales_db.orders TO 'readonly_user'@'%';

-- 授予多个表的权限
GRANT SELECT, INSERT ON inventory_db.products, inventory_db.stock TO 'inventory_user'@'192.168.1.%';

3.3 授予列级别权限

语法:

GRANT privileges (column1, column2, ...) ON database_name.table_name TO 'username'@'host';

示例:

-- 授予特定列的更新权限
GRANT UPDATE (email, phone) ON customers_db.users TO 'support_user'@'localhost';

-- 授予多列的查询权限
GRANT SELECT (id, name, email) ON hr_db.employees TO 'hr_viewer'@'%';

-- 授予插入特定列的权限
GRANT INSERT (name, email, department) ON hr_db.employees TO 'hr_assistant'@'192.168.1.%';

3.4 授予存储过程/函数权限

语法:

GRANT EXECUTE ON PROCEDURE database_name.procedure_name TO 'username'@'host';
GRANT EXECUTE ON FUNCTION database_name.function_name TO 'username'@'host';

示例:

-- 授予存储过程执行权限
GRANT EXECUTE ON PROCEDURE sales_db.calculate_revenue TO 'report_user'@'%';

-- 授予函数执行权限
GRANT EXECUTE ON FUNCTION utils.format_date TO 'app_user'@'localhost';

-- 授予所有存储过程和函数的执行权限
GRANT EXECUTE ON database_name.* TO 'app_user'@'%';

3.5 授予所有权限

全局权限:

GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION;

注意: 全局权限应谨慎授予,通常只给数据库管理员使用。

4. 权限撤销操作

4.1 撤销数据库级别权限

语法:

REVOKE privileges ON database_name.* FROM 'username'@'host';

示例:

-- 撤销删除权限
REVOKE DELETE ON app_db.* FROM 'app_user'@'localhost';

-- 撤销多个权限
REVOKE INSERT, UPDATE ON sales_db.* FROM 'readonly_user'@'%';

4.2 撤销表级别权限

语法:

REVOKE privileges ON database_name.table_name FROM 'username'@'host';

示例:

-- 撤销表的更新权限
REVOKE UPDATE ON customers_db.users FROM 'support_user'@'localhost';

-- 撤销多个表的权限
REVOKE SELECT ON sales_db.orders, sales_db.order_items FROM 'temp_user'@'%';

4.3 撤销所有权限

撤销特定数据库的所有权限:

REVOKE ALL PRIVILEGES ON database_name.* FROM 'username'@'host';

撤销所有数据库的所有权限:

REVOKE ALL PRIVILEGES ON *.* FROM 'username'@'host';

示例:

-- 撤销用户在特定数据库的所有权限
REVOKE ALL PRIVILEGES ON test_db.* FROM 'test_user'@'%';

-- 撤销用户的权限授予权限
REVOKE GRANT OPTION ON *.* FROM 'power_user'@'localhost';

5. 权限查看

5.1 查看用户列表

-- MySQL 5.7及以上
SELECT user, host FROM mysql.user;

-- 查看所有用户信息
SELECT user, host, authentication_string, plugin FROM mysql.user;

-- 查看活跃用户
SELECT user, host, max_connections, max_user_connections 
FROM mysql.user WHERE user <> '';

5.2 查看用户权限

语法:

SHOW GRANTS FOR 'username'@'host';

示例:

-- 查看用户权限
SHOW GRANTS FOR 'app_user'@'localhost';

-- 查看所有权限详情
SHOW GRANTS FOR 'root'@'localhost';

5.3 查看当前用户权限

SHOW GRANTS;

5.4 查看权限表结构

-- 查看用户表
DESCRIBE mysql.user;

-- 查看权限表
DESCRIBE mysql.db;
DESCRIBE mysql.tables_priv;
DESCRIBE mysql.columns_priv;
DESCRIBE mysql.procs_priv;

6. 权限刷新与生效

6.1 刷新权限

当修改权限后,需要刷新权限表使更改生效:

FLUSH PRIVILEGES;

6.2 权限生效时间

  • 新权限:立即生效(除了已连接的会话)
  • 撤销权限:对新会话立即生效,对现有会话在下次操作时生效
  • 密码修改:对新连接立即生效,现有连接不受影响

7. 常见权限组合示例

7.1 只读用户

-- 创建只读用户
CREATE USER 'readonly'@'%' IDENTIFIED BY 'ReadonlyPass123!';

-- 授予查询权限
GRANT SELECT ON database_name.* TO 'readonly'@'%';

-- 授予特定表的只读权限
GRANT SELECT ON database_name.important_table TO 'readonly'@'%';

7.2 数据维护用户

-- 创建数据维护用户
CREATE USER 'data_maintain'@'localhost' IDENTIFIED BY 'MaintainPass456!';

-- 授予增删改查权限
GRANT SELECT, INSERT, UPDATE, DELETE ON app_db.* TO 'data_maintain'@'localhost';

-- 不授予结构修改权限

7.3 开发测试用户

-- 创建开发用户
CREATE USER 'dev_user'@'%' IDENTIFIED BY 'DevPass789!';

-- 授予开发所需权限
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX 
ON test_db.* TO 'dev_user'@'%';

-- 授予存储过程权限
GRANT EXECUTE, CREATE ROUTINE, ALTER ROUTINE ON test_db.* TO 'dev_user'@'%';

7.4 管理员用户

-- 创建管理员用户
CREATE USER 'db_admin'@'localhost' IDENTIFIED BY 'AdminPass123!';

-- 授予数据库管理权限
GRANT ALL PRIVILEGES ON *.* TO 'db_admin'@'localhost' WITH GRANT OPTION;

-- 移除危险权限
REVOKE SHUTDOWN, FILE, SUPER ON *.* FROM 'db_admin'@'localhost';

8. 安全最佳实践

8.1 最小权限原则

  • 只授予用户完成工作所需的最小权限
  • 定期审查和回收不必要的权限
  • 使用角色或权限组管理权限

8.2 密码策略

-- 设置密码验证插件
INSTALL PLUGIN validate_password SONAME 'validate_password.so';

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

-- 设置密码策略
SET GLOBAL validate_password_policy = 'STRONG';
SET GLOBAL validate_password_length = 12;
SET GLOBAL validate_password_number_count = 2;
SET GLOBAL validate_password_special_char_count = 2;

8.3 远程访问控制

-- 限制远程访问IP
CREATE USER 'remote_admin'@'192.168.1.%' IDENTIFIED BY 'SecurePass123!';

-- 禁止root远程登录
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');

-- 使用防火墙限制MySQL端口访问
-- iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 3306 -j ACCEPT
-- iptables -A INPUT -p tcp --dport 3306 -j DROP

8.4 定期权限审计

-- 审计用户权限脚本
SELECT user, host, 
       IF(Select_priv='Y','SELECT,','') AS Select_priv,
       IF(Insert_priv='Y','INSERT,','') AS Insert_priv,
       IF(Update_priv='Y','UPDATE,','') AS Update_priv,
       IF(Delete_priv='Y','DELETE,','') AS Delete_priv,
       IF(Create_priv='Y','CREATE,','') AS Create_priv,
       IF(Drop_priv='Y','DROP,','') AS Drop_priv,
       IF(Reload_priv='Y','RELOAD,','') AS Reload_priv,
       IF(Shutdown_priv='Y','SHUTDOWN,','') AS Shutdown_priv,
       IF(Process_priv='Y','PROCESS,','') AS Process_priv,
       IF(File_priv='Y','FILE,','') AS File_priv,
       IF(Grant_priv='Y','GRANT OPTION,','') AS Grant_priv,
       IF(References_priv='Y','REFERENCES,','') AS References_priv,
       IF(Index_priv='Y','INDEX,','') AS Index_priv,
       IF(Alter_priv='Y','ALTER,','') AS Alter_priv,
       IF(Show_db_priv='Y','SHOW DATABASES,','') AS Show_db_priv,
       IF(Super_priv='Y','SUPER,','') AS Super_priv
FROM mysql.user
ORDER BY user, host;

8.5 使用SSL加密连接

-- 创建使用SSL的用户
CREATE USER 'secure_user'@'%' 
IDENTIFIED BY 'SecurePass123!' 
REQUIRE SSL;

-- 要求特定的SSL证书
CREATE USER 'cert_user'@'%' 
IDENTIFIED BY 'CertPass123!' 
REQUIRE X509;

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

9. 故障排查

9.1 连接问题

-- 检查用户是否存在
SELECT user, host FROM mysql.user WHERE user='username';

-- 检查用户密码是否正确
SELECT user, host, authentication_string FROM mysql.user WHERE user='username';

-- 检查连接权限
SHOW GRANTS FOR 'username'@'host';

-- 检查防火墙设置
-- netstat -tlnp | grep 3306
-- iptables -L -n

9.2 权限不生效

-- 刷新权限
FLUSH PRIVILEGES;

-- 检查权限表
SELECT * FROM mysql.db WHERE user='username';
SELECT * FROM mysql.tables_priv WHERE user='username';

-- 检查当前会话权限
SHOW GRANTS;

-- 重新连接数据库

9.3 密码重置

MySQL 5.7及以上:

-- 重置root密码
ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewRootPass123!';

-- 跳过密码验证启动(紧急情况)
-- mysqld_safe --skip-grant-tables &
-- mysql -u root
-- FLUSH PRIVILEGES;
-- ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewPassword!';

10. 权限管理脚本示例

10.1 创建应用用户脚本

-- 创建应用用户脚本
DELIMITER //

CREATE PROCEDURE create_app_user(
    IN p_username VARCHAR(32),
    IN p_host VARCHAR(60),
    IN p_password VARCHAR(32),
    IN p_database VARCHAR(64)
)
BEGIN
    -- 创建用户
    SET @create_user_sql = CONCAT(
        'CREATE USER ''', p_username, '''@''', p_host, ''' IDENTIFIED BY ''', p_password, ''''
    );
    PREPARE stmt FROM @create_user_sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
    
    -- 授予权限
    SET @grant_sql = CONCAT(
        'GRANT SELECT, INSERT, UPDATE, DELETE ON ', p_database, '.* TO ''', p_username, '''@''', p_host, ''''
    );
    PREPARE stmt FROM @grant_sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
    
    -- 刷新权限
    FLUSH PRIVILEGES;
    
    SELECT CONCAT('User ', p_username, '@', p_host, ' created successfully with access to ', p_database) AS message;
END //

DELIMITER ;

-- 使用示例
CALL create_app_user('myapp', '%', 'AppPass123!', 'my_database');

10.2 权限审计脚本

-- 权限审计脚本
DELIMITER //

CREATE PROCEDURE audit_user_permissions()
BEGIN
    -- 创建临时表存储结果
    CREATE TEMPORARY TABLE IF NOT EXISTS permission_audit (
        username VARCHAR(32),
        host VARCHAR(60),
        permission_level VARCHAR(20),
        database_name VARCHAR(64),
        table_name VARCHAR(64),
        privileges TEXT
    );
    
    -- 插入全局权限
    INSERT INTO permission_audit
    SELECT user, host, 'GLOBAL', '*', '*', 
           CONCAT_WS(', ',
               IF(Select_priv='Y','SELECT',''),
               IF(Insert_priv='Y','INSERT',''),
               IF(Update_priv='Y','UPDATE',''),
               IF(Delete_priv='Y','DELETE',''),
               IF(Create_priv='Y','CREATE',''),
               IF(Drop_priv='Y','DROP',''),
               IF(Reload_priv='Y','RELOAD',''),
               IF(Shutdown_priv='Y','SHUTDOWN',''),
               IF(Process_priv='Y','PROCESS',''),
               IF(File_priv='Y','FILE',''),
               IF(Grant_priv='Y','GRANT OPTION',''),
               IF(References_priv='Y','REFERENCES',''),
               IF(Index_priv='Y','INDEX',''),
               IF(Alter_priv='Y','ALTER',''),
               IF(Show_db_priv='Y','SHOW DATABASES',''),
               IF(Super_priv='Y','SUPER','')
           )
    FROM mysql.user
    WHERE user <> '';
    
    -- 插入数据库权限
    INSERT INTO permission_audit
    SELECT user, host, 'DATABASE', db, '*', 
           CONCAT_WS(', ',
               IF(Select_priv='Y','SELECT',''),
               IF(Insert_priv='Y','INSERT',''),
               IF(Update_priv='Y','UPDATE',''),
               IF(Delete_priv='Y','DELETE',''),
               IF(Create_priv='Y','CREATE',''),
               IF(Drop_priv='Y','DROP',''),
               IF(Grant_priv='Y','GRANT OPTION',''),
               IF(References_priv='Y','REFERENCES',''),
               IF(Index_priv='Y','INDEX',''),
               IF(Alter_priv='Y','ALTER','')
           )
    FROM mysql.db;
    
    -- 返回审计结果
    SELECT * FROM permission_audit ORDER BY username, host, permission_level;
    
    -- 清理临时表
    DROP TEMPORARY TABLE IF EXISTS permission_audit;
END //

DELIMITER ;

-- 使用示例
CALL audit_user_permissions();

10.3 批量权限管理

-- 批量创建测试用户
DELIMITER //

CREATE PROCEDURE create_test_users(
    IN p_prefix VARCHAR(20),
    IN p_count INT,
    IN p_database VARCHAR(64)
)
BEGIN
    DECLARE i INT DEFAULT 1;
    
    WHILE i <= p_count DO
        SET @username = CONCAT(p_prefix, '_user_', LPAD(i, 3, '0'));
        SET @password = CONCAT('TestPass_', LPAD(i, 3, '0'), '!');
        
        -- 创建用户
        SET @create_sql = CONCAT(
            'CREATE USER ''', @username, '''@''%'' IDENTIFIED BY ''', @password, ''''
        );
        PREPARE stmt FROM @create_sql;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
        
        -- 授予权限
        SET @grant_sql = CONCAT(
            'GRANT SELECT, INSERT, UPDATE ON ', p_database, '.* TO ''', @username, '''@''%'''
        );
        PREPARE stmt FROM @grant_sql;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
        
        SET i = i + 1;
    END WHILE;
    
    FLUSH PRIVILEGES;
    
    SELECT CONCAT('Created ', p_count, ' test users with prefix ', p_prefix) AS message;
END //

DELIMITER ;

-- 使用示例
CALL create_test_users('test', 5, 'test_database');

四下皆无人