You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何创建拥有CREATE USER权限但无法访问新数据库的MySQL用户?

如何创建拥有CREATE USER权限但无法访问新数据库的MySQL用户

这个需求的核心是权限最小化——既要让用户能创建其他用户并分配指定权限,又要严格限制它自身的数据库访问能力。下面分MySQL版本给出具体方案:

一、MySQL 8.0及以上(推荐用角色实现)

MySQL 8.0引入的角色功能可以完美分离「权限拥有」和「权限使用」,是最优雅的解决方案:

步骤1:创建用于转授的角色

先定义两个角色,分别对应给write_user分配的权限:

-- 角色1:拥有main_db的读写权限,且可以转授给其他用户
CREATE ROLE 'main_db_writer'@'localhost';
GRANT CREATE, UPDATE, INSERT, DELETE, SELECT ON main_db.* TO 'main_db_writer'@'localhost' WITH GRANT OPTION;

-- 角色2:允许创建专属user_db并拥有该库的全部权限
CREATE ROLE 'user_db_creator'@'localhost';
GRANT CREATE DATABASE ON *.* TO 'user_db_creator'@'localhost';
GRANT ALL PRIVILEGES ON `user\_db\_%`.* TO 'user_db_creator'@'localhost' WITH GRANT OPTION;

步骤2:创建受限的admin用户

创建limited_admin,只给它必要的权限,且默认不激活角色:

-- 创建用户
CREATE USER 'limited_admin'@'localhost' IDENTIFIED BY '你的安全密码';

-- 授予创建用户的权限
GRANT CREATE USER ON *.* TO 'limited_admin'@'localhost';

-- 允许它转授上述两个角色,但不给它自身使用角色的权限
GRANT 'main_db_writer'@'localhost', 'user_db_creator'@'localhost' TO 'limited_admin'@'localhost' WITH GRANT OPTION;

-- 关键:设置默认不激活角色,确保它自身无法使用角色的权限
SET DEFAULT ROLE NONE TO 'limited_admin'@'localhost';

效果验证

limited_admin可以:

  • 创建新的write_user
  • main_db_writeruser_db_creator角色授予write_user
    但自身无法访问main_db或任何新创建的user_db,也不能直接创建数据库(只能通过转授角色让其他人创建)。

二、MySQL 5.x(无角色,用存储过程实现)

旧版本没有角色功能,我们可以用存储过程封装创建用户和授权的逻辑,让limited_admin只能通过调用存储过程完成操作:

步骤1:创建存储过程(用root用户执行)

DELIMITER //
CREATE PROCEDURE create_authorized_write_user(
    IN username VARCHAR(100), 
    IN host VARCHAR(100), 
    IN password VARCHAR(255)
)
BEGIN
    -- 创建write_user
    SET @create_sql = CONCAT('CREATE USER ''', username, '''@''', host, ''' IDENTIFIED BY ''', password, ''';');
    PREPARE stmt FROM @create_sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;

    -- 授予main_db的读写权限
    SET @grant_main_sql = CONCAT('GRANT CREATE, UPDATE, INSERT, DELETE, SELECT ON main_db.* TO ''', username, '''@''', host, ''';');
    PREPARE stmt FROM @grant_main_sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;

    -- 授予创建专属user_db的权限
    SET @grant_user_db_sql = CONCAT('GRANT CREATE DATABASE ON *.* TO ''', username, '''@''', host, ''';');
    PREPARE stmt FROM @grant_user_db_sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;

    -- 授予专属user_db的全部权限
    SET @grant_user_db_all_sql = CONCAT('GRANT ALL PRIVILEGES ON `', username, '_db`.* TO ''', username, '''@''', host, ''';');
    PREPARE stmt FROM @grant_user_db_all_sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
END //
DELIMITER ;

步骤2:给limited_admin授权

-- 创建用户
CREATE USER 'limited_admin'@'localhost' IDENTIFIED BY '你的安全密码';

-- 只允许它调用这个存储过程,不给任何其他权限
GRANT EXECUTE ON PROCEDURE create_authorized_write_user TO 'limited_admin'@'localhost';

效果验证

limited_admin只能通过调用存储过程创建符合要求的write_user,自身没有任何数据库访问权限,也不能直接创建其他用户或分配额外权限。

关键注意事项

  1. 绝对避免全局WITH GRANT OPTION:全局的WITH GRANT OPTION会让用户获得所有数据库的权限,完全违背需求,一定要把权限范围限制在特定数据库或角色上。
  2. 权限最小化:只给limited_admin完成工作必需的权限,不要多给。
  3. 测试权限边界:创建后一定要测试:
    • 尝试访问main_db:应该被拒绝
    • 尝试创建用户并分配指定权限:应该成功
    • 尝试分配超出范围的权限(比如DROP数据库):应该被拒绝

内容的提问来源于stack exchange,提问作者iWizard

火山引擎 最新活动