set default role 仅控制登录初始角色,无法阻止用户后续用 set role 切换或禁用角色;mandatory_roles 才能强制激活且不可绕过,需 set persist 配置并确保角色存在、已授权、大小写及引号正确。

MySQL 8.0 无法完全防止用户绕过角色权限限制,但可通过 mandatory_roles 强制激活指定角色,配合 activate_all_roles_on_login = OFF 和显式 SET DEFAULT ROLE 控制最小可绕过面。
为什么 SET DEFAULT ROLE 不足以阻止用户跳过角色
用户登录后只要拥有 ROLE_ADMIN 权限,就能随时执行 SET ROLE NONE 或 SET ROLE 'other_role' 切换上下文,绕过你设的默认角色。即使没给 ROLE_ADMIN,只要用户被授予多个角色,还能用 SET ROLE 'xxx' 主动切换——而这个操作不需要额外权限,只要该角色已通过 GRANT 分配给他。
常见误判是以为“设了 DEFAULT ROLE 就锁死了权限”,其实它只影响登录初始状态,不阻止后续会话内变更。
-
SET DEFAULT ROLE是声明“登录时自动启用哪些角色”,不是权限防火墙 - 用户执行
SET ROLE NONE后,CURRENT_ROLE()返回NULL,SHOW GRANTS只显示直授权限(如果有的话) - 若用户同时有
SYSTEM_VARIABLES_ADMIN,甚至能临时关掉activate_all_roles_on_login影响全局行为
用 mandatory_roles 强制绑定核心角色
mandatory_roles 是唯一能真正“强制”的机制:它让某些角色在每次连接建立时无条件激活,且无法被 SET ROLE 覆盖或禁用。但它不是为普通业务角色设计的,而是面向 DBA 级管控场景。
设置方式必须用 SET PERSIST(写入 mysqld-auto.cnf),且角色名需用逗号分隔、无空格:
SET PERSIST mandatory_roles = '"auditor","security_monitor"';
注意:mandatory_roles 中的角色必须已存在、已被授予至少一个用户,并且不能包含当前连接用户自己(否则启动失败)。它对大小写敏感,且引号必须是双引号(MySQL 内部解析要求)。
- 一旦设置,所有新连接都会自动激活这些角色,
SET ROLE NONE对它们无效 - 但已有连接不受影响,需重连才生效
- 若角色不存在或拼写错误,MySQL 启动时会报错并拒绝加载,所以务必先确认
SELECT * FROM mysql.role_edges WHERE from_host = '%' AND from_user IN ('auditor', 'security_monitor'); - 不能用通配符或正则,只能列具体角色名
检查 mandatory_roles 是否生效及当前强制角色
运行以下命令验证配置是否落地且被识别:
SELECT @@mandatory_roles;
返回值应为带双引号的逗号分隔字符串,如 "\"auditor\",\"security_monitor\""。若为空或报错 Unknown system variable,说明版本低于 8.0.16(mandatory_roles 自此版本引入)。
要确认某用户当前连接是否真的加载了强制角色,不能只看 CURRENT_ROLE() —— 它只显示手动或默认激活的角色,不体现 mandatory_roles 的隐式激活。正确方法是:
- 执行
SHOW GRANTS USING 'auditor';,如果返回具体权限,说明该强制角色已生效 - 尝试
SET ROLE NONE;后再查CURRENT_ROLE(),若仍显示'auditor',即证明它是 mandatory 的 - 查系统表:
SELECT * FROM performance_schema.variables_info WHERE VARIABLE_NAME = 'mandatory_roles';可看变量是否被持久化
容易被忽略的兼容性与安全边界
mandatory_roles 不是银弹。它只解决“角色是否激活”问题,不解决“角色里有没有漏洞权限”。比如你把 auditor 设为 mandatory,但当初给它授了 GRANT ALL ON *.*,那所有用户连接后都拿到全库权限——这比绕过还危险。
真正安全的路径是:先用最小权限原则定义角色,再用 mandatory_roles 锁定其激活,最后禁用用户侧的 ROLE_ADMIN 和 SYSTEM_VARIABLES_ADMIN 权限。
- 普通应用用户不应拥有
ROLE_ADMIN;DBA 才需要,且应单独建专用管理账号 -
mandatory_roles无法防御代理用户(PROXY)场景,代理用户的权限继承独立于原用户,需单独配置 - 备份恢复时,
mysqldump --all-databases不导出mandatory_roles设置,目标实例需手动重建











