MySQL8安全指南之账号控制与账户管理:使用角色

使用角色

MySQL 角色是一个命名的权限集合。与用户帐户一样,角色也可以被授予或撤消权限。

用户帐户可以被授予角色,角色将授予帐户与每个角色关联的权限。这允许将一组权限分配给帐户,并提供了授予单独权限的方便替代方案。

以下列表总结了 MySQL 提供的角色管理功能:

  • CREATE ROLE 和 DROP ROLE 创建和删除角色。

  • GRANTREVOKE 为账户和角色分配权限和撤销权限

  • SHOW GRANTS 显示用户帐户分配的角色以及角色的权限。

  • SET DEFAULT ROLE 默认情况下制定哪些账户角色是活跃的。

  • SET ROLE 更改当前会话中活跃的角色。

  • CURRENT_ROLE() 函数显示当前会话中的活跃角色。

  • 当用户登录到服务器时,mandatory_rolesactivate_all_roles_on_login 系统变量允许定义强制角色和自动激活授予的角色。

创建角色并为其授予权限

考虑这个场景:

  • 应用程序使用名为 app_db 的数据库。
  • 与应用程序相关联的帐户可以是创建和维护应用程序的开发人员的帐户,也可以是与应用程序交互的用户的帐户。
  • 开发人员需要完全访问数据库。有些用户只需要读权限,有些用户需要读/写权限。

若要避免单独向多个用户帐户授予权限,请创建角色作为所需权限集的名称。这使得通过授予适当的角色,可以很容易地向用户帐户授予所需的权限。

要创建角色,请使用 CREATE ROLE 语句:

CREATE ROLE 'app_developer', 'app_read', 'app_write';

角色名称与用户帐户名称非常相似,由'user_name'@'host_name'格式的用户部分和主机部分组成。主机部分,如果省略,默认为 '%'。用户和主机部分可以不加引号,除非它们包含特殊字符,例如 -%。与帐户名称不同,角色名称的用户部分不能为空。

要给角色分配权限,执行GRANT语句,语法与给用户帐户分配权限相同:

GRANT ALL ON app_db.* TO 'app_developer';
GRANT SELECT ON app_db.* TO 'app_read';
GRANT INSERT, UPDATE, DELETE ON app_db.* TO 'app_write';

现在假设您需要一个开发者帐户、两个需要只读访问权限的用户帐户和一个需要读/写访问权限的用户帐户。使用 CREATE USER 创建账户:

CREATE USER 'dev1'@'localhost' IDENTIFIED BY 'dev1pass';
CREATE USER 'read_user1'@'localhost' IDENTIFIED BY 'read_user1pass';
CREATE USER 'read_user2'@'localhost' IDENTIFIED BY 'read_user2pass';
CREATE USER 'rw_user1'@'localhost' IDENTIFIED BY 'rw_user1pass';

为用户账户分配角色:

GRANT 'app_developer' TO 'dev1'@'localhost';
GRANT 'app_read' TO 'read_user1'@'localhost', 'read_user2'@'localhost';
GRANT 'app_read', 'app_write' TO 'rw_user1'@'localhost';

rw_user1帐户的GRANT语句授予读写角色,这些角色组合起来提供所需的读写权限。

授予帐户角色的 GRANT 语法与授予权限的语法不同:分配权限有ON子句,分配角色没有ON语句。由于语法不同,您不能在同一语句中混合分配权限和角色。从 MySQL 8.0.16 开始,角色不能授予匿名用户。

角色在创建时被锁定,没有密码,并且被分配了默认的身份验证插件(具有全局CREATE USER权限的用户可以稍后使用ALTER USER语句更改这些角色属性)

锁定时,角色不能用于身份验证。如果未锁定,则可以使用角色进行认证。这是因为角色和用户都是授权标识符,它们有很多共同点,但几乎没有区别。

定义强制性角色

可以通过在mandatory_roles系统变量的值中命名角色,将它们指定为强制角色。服务器将强制角色视为授予所有用户的角色,因此不需要显式地授予任何帐户。

要在服务器启动时指定强制角色,请在服务器 my.cnf 文件中定义强制角色:

[mysqld]
mandatory_roles='role1,role2@localhost,r3@%.example.com'

在运行时设置和持久化mandatory_roles,,请使用以下语句:

SET PERSIST mandatory_roles = 'role1,role2@localhost,r3@%.example.com';

SET PERSIST为正在运行的MySQL实例设置值。它还保存该值,使其保留到后续服务器重新启动时。若要更改正在运行的MySQL实例的值,而不将其保留到后续重启中,请使用GLOBAL关键字而不是PERSIST

设置mandatory_roles需要ROLE_ADMIN权限,以及设置全局系统变量所需要的SYSTEM_VARIABLES_ADMIN权限。

强制角色与显式授予的角色一样,在激活之前不会生效。在登录时,如果activate_all_roles_on_login系统变量是启用的,则会对所有被授予的角色进行角色激活,或者对其他设置为默认角色的角色进行角色激活。在运行时,SET ROLE激活角色。

mandatory_roles命名的角色不能通过REVOKE撤销,也不能通过DROP ROLEDROP USER删除。

若要防止在默认情况下将会话设为系统会话,具有SYSTEM_USER权限的角色不能在mandatory_roles系统变量的值中列出:

  • 如果在启动时为mandatory_roles 分配了具有SYSTEM_USER 权限的角色,则服务器将一条消息写入错误日志并退出。

  • 如果在运行时为mandatory_roles 分配了具有SYSTEM_USER 权限的角色,则会发生错误并且mandatory_roles 值保持不变。

如果在mandatory_roles值中出现的角色名在mysql.user系统表中不存在,该角色不会授权给用户。当服务器尝试为用户激活角色时,它不会将不存在的角色视为强制性角色并将警告写入错误日志。如果该角色稍后创建并使其生效,则可能需要FLUSH PRIVILEGES才能使服务器将其视为强制角色。

检查角色权限

要验证分配给帐户的权限,请使用 SHOW GRANTS。例如:

mysql> SHOW GRANTS FOR 'dev1'@'localhost';
+-------------------------------------------------+
| Grants for dev1@localhost                       |
+-------------------------------------------------+
| GRANT USAGE ON *.* TO `dev1`@`localhost`        |
| GRANT `app_developer`@`%` TO `dev1`@`localhost` |
+-------------------------------------------------+

但是,这仅仅显示了每个被授予的角色,而没有将其“扩展”为角色所代表的权限。要同时显示角色权限,请添加一个USING子句

mysql> SHOW GRANTS FOR 'dev1'@'localhost' USING 'app_developer';
+----------------------------------------------------------+
| Grants for dev1@localhost                                |
+----------------------------------------------------------+
| GRANT USAGE ON *.* TO `dev1`@`localhost`                 |
| GRANT ALL PRIVILEGES ON `app_db`.* TO `dev1`@`localhost` |
| GRANT `app_developer`@`%` TO `dev1`@`localhost`          |
+----------------------------------------------------------+

类似地验证其他类型的用户:

mysql> SHOW GRANTS FOR 'read_user1'@'localhost' USING 'app_read';+--------------------------------------------------------+| Grants for read_user1@localhost                        |+--------------------------------------------------------+| GRANT USAGE ON *.* TO `read_user1`@`localhost`         || GRANT SELECT ON `app_db`.* TO `read_user1`@`localhost` || GRANT `app_read`@`%` TO `read_user1`@`localhost`       |+--------------------------------------------------------+mysql> SHOW GRANTS FOR 'rw_user1'@'localhost' USING 'app_read', 'app_write';+------------------------------------------------------------------------------+| Grants for rw_user1@localhost                                                |+------------------------------------------------------------------------------+| GRANT USAGE ON *.* TO `rw_user1`@`localhost`                                 || GRANT SELECT, INSERT, UPDATE, DELETE ON `app_db`.* TO `rw_user1`@`localhost` || GRANT `app_read`@`%`,`app_write`@`%` TO `rw_user1`@`localhost`               |+------------------------------------------------------------------------------+

激活角色

在帐户会话中,授予用户帐户的角色可以是活跃的,也可以是不活跃的。如果一个被授予的角色在一个会话中是活跃的,那么它的权限将被应用;否则,它们就不会被应用。要确定当前会话中哪些角色是活跃的,请使用CURRENT_ROLE()函数。

默认情况下,向帐户授予角色或在mandatory_roles 系统变量值中命名它不会自动导致该角色在帐户会话中变为活跃状态。例如,因为在前面的讨论中到目前为止还没有激活rw_user1角色,如果你以rw_user1的身份连接服务器并调用CURRENT_ROLE()函数,结果是NONE(没有激活的角色):

mysql> SELECT CURRENT_ROLE();+----------------+| CURRENT_ROLE() |+----------------+| NONE           |+----------------+

要指定每次用户连接到服务器并进行身份验证时应该激活哪些角色,请使用SET DEFAULT ROLE。要为之前创建的每个帐户设置默认角色,请使用以下语句:

SET DEFAULT ROLE ALL TO  'dev1'@'localhost',  'read_user1'@'localhost',  'read_user2'@'localhost',  'rw_user1'@'localhost';

现在,如果您以 rw_user1 身份连接,则 CURRENT_ROLE() 返回值为活跃的角色:

mysql> SELECT CURRENT_ROLE();+--------------------------------+| CURRENT_ROLE()                 |+--------------------------------+| `app_read`@`%`,`app_write`@`%` |+--------------------------------+

要在用户连接到服务器时自动激活所有明确授予和强制的角色,请启用 activate_all_roles_on_login 系统变量。默认情况下,禁用自动角色激活。

在会话中,用户可以执行 SET ROLE 来更改活跃的角色集。例如,对于 rw_user1

mysql> SET ROLE NONE; SELECT CURRENT_ROLE();+----------------+| CURRENT_ROLE() |+----------------+| NONE           |+----------------+mysql> SET ROLE ALL EXCEPT 'app_write'; SELECT CURRENT_ROLE();+----------------+| CURRENT_ROLE() |+----------------+| `app_read`@`%` |+----------------+mysql> SET ROLE DEFAULT; SELECT CURRENT_ROLE();+--------------------------------+| CURRENT_ROLE()                 |+--------------------------------+| `app_read`@`%`,`app_write`@`%` |+--------------------------------+

第一个SET ROLE语句禁用所有角色。第二种方法使rw_user1是只读的。第三个恢复默认角色。

撤销角色或角色权限

正如可以向帐户授予角色一样,它们也可以从帐户中撤销:

REVOKE role FROM user;

mandatory_roles 系统变量值中命名的角色不能被撤销。

还可以对角色应用REVOKE来修改授予它的权限。这不仅影响角色本身,还影响授予该角色的任何帐户。假设您想暂时将所有应用程序用户设为只读。为此,请使用REVOKEapp_write角色中撤消修改权限:

REVOKE INSERT, UPDATE, DELETE ON app_db.* FROM 'app_write';

删除角色

删除角色将会从授予该角色的每个帐户中撤销该角色。

mandatory_roles 系统变量值中命名的角色不能被删除。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值