MySQL 8.0.18:数据库全权限角色无法让用户创建对应数据库
MySQL角色权限与直接用户权限的差异解析及解决方案
这个行为符合预期吗?
绝对符合,这不是MySQL的bug,而是它8.0版本里角色和直接用户权限的检查机制不一样导致的。
咱们来理清楚差异点:
- 当你直接给
joe授予ALL ON joe_db.*时,哪怕joe_db还没创建,MySQL也会把这条权限写到mysql.db系统表中存着。等你用joe去创建joe_db的时候,权限检查会看到系统表已经有这个用户对该数据库的权限记录,就直接允许创建了。你当时看到的那个1 warning只是提醒你joe_db还不存在,但不影响权限规则的保存。 - 但用角色
joe_role授同样权限的时候,角色的权限不会提前写入mysql.db表——只有当joe_db真的存在了,角色的权限才会生效。所以在数据库没创建的时候,激活角色的joe根本没有创建这个库的权限,自然就报错了。
不授全局ALL权限,怎么让角色能创建指定数据库?
核心是要给角色单独加创建数据库的权限,遵循最小权限原则,别一股脑给全局ALL。具体操作分两步:
正确的授权操作
-- 创建角色 CREATE ROLE 'joe_role'; -- 只给创建数据库的全局权限(仅满足创建需求,不额外授权) GRANT CREATE ON *.* TO 'joe_role'; -- 再给目标数据库的所有对象权限 GRANT ALL ON `joe_db`.* TO 'joe_role'; -- 把角色分配给用户 GRANT `joe_role` TO `joe`@'localhost';
验证权限
$ mysql -ujoe -p1234 -hlocalhost mysql> SET ROLE `joe_role`; Query OK, 0 rows affected (0.00 sec) mysql> CREATE DATABASE `joe_db`; Query OK, 1 row affected (0.01 sec) mysql> DROP DATABASE `joe_db`; Query OK, 0 rows affected (0.01 sec)
更精细的权限控制(可选)
如果想严格限制joe只能创建joe_db这一个库,MySQL本身没法直接指定“仅允许创建某一个库”的权限,但可以用触发器实现拦截:
- 先按上面的步骤给角色全局
CREATE权限 - 用超级用户创建触发器,拦截非
joe_db的创建请求:
DELIMITER // CREATE TRIGGER restrict_joe_database BEFORE CREATE ON SCHEMA FOR EACH STATEMENT BEGIN IF CURRENT_USER() = 'joe@localhost' AND SCHEMA_NAME() != 'joe_db' THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '你只能创建joe_db数据库'; END IF; END // DELIMITER ;
这样既满足了创建指定库的需求,又不会给用户过度授权。
内容的提问来源于stack exchange,提问作者porkbrain




