MySQL角色是一个命名的特权集合。与用户帐户一样,角色可以被授予特权,也可以被撤销特权。
用户帐户可以被授予角色,这将向帐户授予与每个角色相关联的特权。这支持向帐户分配一组特权,并提供了一种授予个别特权的方便替代方案,既可以概念化所需的特权分配,也可以实现它们。
下面的列表总结了MySQL提供的角色管理功能:
秀奖助金
显示用户帐户和角色的权限和角色分配。设置默认角色
指定默认情况下哪些帐户角色是活动的。设置角色
更改当前会话中的活动角色。的
CURRENT_ROLE ()
函数显示当前会话中的活动角色。的
mandatory_roles
而且activate_all_roles_on_login
系统变量支持在用户登录到服务器时定义强制角色和自动激活被授予的角色。
有关各个角色操作语句的描述(包括使用它们所需的特权),请参见第13.7.1节“帐户管理报表”.下面的讨论提供了角色使用的示例。除非另有说明,此处所示的SQL语句应该使用具有足够管理权限的MySQL帐户执行,例如根
帐户。
考虑一下这个场景:
应用程序使用名为
app_db
.与应用程序相关联的,可以为创建和维护应用程序的开发人员以及与应用程序交互的用户提供帐户。
开发人员需要对数据库的完全访问权限。有些用户只需要读访问权,有些用户需要读/写访问权。
为了避免向可能多个用户帐户分别授予权限,请将角色创建为所需权限集的名称。通过授予适当的角色,可以很容易地向用户帐户授予所需的特权。
创建角色时,使用创建角色
声明:
创建角色app_developer, app_read, app_write;
角色名很像用户帐户名,由其中的用户部分和主机部分组成'
格式。如果省略主机部分,默认为user_name
“@”host_name
'“%”
.用户和主机部分可以不加引号,除非它们包含特殊字符,例如-
或%
.与帐户名不同,角色名的用户部分不能为空。有关更多信息,请参见第6.2.5节“指定角色名称”.
要为角色分配特权,请执行格兰特
使用与为用户帐户分配特权相同语法的语句:
授予app_db上的所有权限。*“app_developer”;在app_db上授予SELECT权限。*“app_read”;授予app_db的插入、更新、删除权限。*“app_write”;
现在假设您最初需要一个开发人员帐户、两个需要只读访问的用户帐户和一个需要读/写访问的用户帐户。使用创建用户
创建帐户。
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';
要为每个用户帐户分配所需的特权,您可以使用格兰特
与刚才显示的形式相同的语句,但这需要为每个用户枚举单独的特权。相反,使用另一种选择格兰特
允许授予角色而不是特权的语法:
授'app_developer'给'dev1'@'localhost'GRANT 'app_read' TO 'read_user1'@'localhost', 'read_user2'@'localhost';GRANT 'app_read', 'app_write' TO 'rw_user1'@'localhost';
的格兰特
声明的rw_user1
Account授予读和写角色,它们结合起来提供所需的读和写权限。
的格兰特
向帐户授予角色的语法与授予特权的语法是不同的在
子句来分配特权,而没有在
子句来分配角色。因为语法是不同的,所以不能在同一条语句中混合分配特权和角色。(允许为一个帐户分配特权和角色,但必须使用单独的格兰特
语句,每个语句的语法都与授予的内容相适应。)从MySQL 8.0.16开始,角色不能授予匿名用户。
角色在创建时是锁定的,没有密码,并被分配到默认的身份验证插件。方法可以更改这些角色属性改变用户
语句,由具有全局创建用户
特权。)
锁定时,角色不能用于对服务器进行身份验证。如果解锁,角色可以用于身份验证。这是因为角色和用户都是授权标识符,它们有很多共同之处,几乎没有区别。另请参阅用户和角色互换性.
类的值中命名角色,可以将角色指定为必填项mandatory_roles
系统变量。服务器将强制角色视为授予所有用户的角色,因此不需要显式地将其授予任何帐户。
若要在服务器启动时指定必须的角色,请定义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';
设置保存
为正在运行的MySQL实例设置一个值。它还会保存该值,使其保留到后续服务器重新启动时。要更改正在运行的MySQL实例的值,而不将其保留到后续重启时,请使用全球
关键字,而不是坚持
.看到第13.7.6.1节“变量赋值的SET语法”.
设置mandatory_roles
要求ROLE_ADMIN
特权,除了SYSTEM_VARIABLES_ADMIN
特权(或已弃用的超级
特权)通常需要设置全局系统变量。
强制角色与显式授予的角色一样,在激活之前不会生效(参见激活的角色).在登录时,对于所有授予的角色,如果activate_all_roles_on_login
系统变量已启用,否则对于设置为默认角色的角色。在运行时,设置角色
激活的角色。
的值中命名的角色mandatory_roles
不能用撤销
或下降下降的作用
或减少用户
.
为防止会话默认情况下成为系统会话,需要具有SYSTEM_USER
的值中不能列出权限mandatory_roles
系统变量:
如果
mandatory_roles
在启动时分配的角色具有SYSTEM_USER
权限时,服务器向错误日志中写入消息并退出。如果
mandatory_roles
在运行时为具有SYSTEM_USER
权限时,会出现错误,并且mandatory_roles
值保持不变。
中命名的角色mandatory_roles
不在mysql.user
系统表,角色不授予用户。当服务器尝试为用户激活角色时,它不会将不存在的角色视为必填项,并向错误日志写入警告。如果角色是稍后创建的,那么就会生效,冲洗的特权
可能需要使服务器将其视为强制性的。
秀奖助金
根据中描述的规则显示必选角色第13.7.7.21节“SHOW授予声明”.
若要验证分配给帐户的权限,请使用秀奖助金
.例如:
mysql> SHOW grant FOR 'dev1'@'localhost';+-------------------------------------------------+ | 资助dev1@localhost | +-------------------------------------------------+ | 格兰特使用*。*“dev1”@“localhost”| |授予“app_developer”@“%”“dev1”@ localhost ` | +-------------------------------------------------+
但是,这显示每个被授予的角色没有”扩大”它指向角色所代表的特权。要显示角色特权,还需要添加一个使用
子句,指定要显示权限的被授予角色:
mysql> SHOW grant FOR 'dev1'@'localhost' USING 'app_developer';+----------------------------------------------------------+ | 资助dev1@localhost | +----------------------------------------------------------+ | 格兰特使用*。授予“app_db”上的所有权限。*“dev1”@“localhost”| |授予“app_developer”@“%”“dev1”@ localhost ` | +----------------------------------------------------------+
类似地验证其他类型的用户:
mysql> SHOW grant FOR 'read_user1'@'localhost' USING 'app_read';+--------------------------------------------------------+ | 资助read_user1@localhost | +--------------------------------------------------------+ | 格兰特使用*。给' read_user1 ' @ ' localhost ' | |指定SELECT ' app_db '*“read_user1”@“localhost”| |授予“app_read”@“%”“read_user1”@ localhost ` | +--------------------------------------------------------+ mysql >显示授予“rw_user1”@“localhost”使用“app_read”、“app_write”;+------------------------------------------------------------------------------+ | 资助rw_user1@localhost | +------------------------------------------------------------------------------+ | 格兰特使用*。为' rw_user1 ' @ ' localhost ' | |授予' app_db '的SELECT, INSERT, UPDATE, DELETE权限。*“rw_user1”@“localhost”| |授予“app_read”@“%”,“app_write”@“%”“rw_user1”@ localhost ` | +------------------------------------------------------------------------------+
秀奖助金
根据中描述的规则显示必选角色第13.7.7.21节“SHOW授予声明”.
在帐户会话中,授予用户帐户的角色可以是活动的或不活动的。如果被授予的角色在会话中是活动的,则应用其特权;否则,他们不会。要确定当前会话中哪些角色是活动的,请使用CURRENT_ROLE ()
函数。
默认情况下,将角色授予帐户或在mandatory_roles
系统变量值不会自动使角色在帐户会话中变为活动状态。例如,因为到目前为止在前面的讨论没有rw_user1
角色已被激活,如果您以rw_user1
并调用CURRENT_ROLE ()
函数,结果是没有一个
(没有发挥积极作用):
mysql >选择CURRENT_ROLE ();+----------------+ | CURRENT_ROLE () | +----------------+ | 没有一个 | +----------------+
要指定在用户每次连接到服务器并进行身份验证时应该激活哪些角色,请使用设置默认角色
.要为之前创建的每个帐户设置默认为所有已分配的角色,使用以下语句:
将DEFAULT ROLE ALL设置为'dev1'@'localhost', 'read_user1'@'localhost', 'read_user2'@'localhost', 'rw_user1'@'localhost';
现在如果你连接成rw_user1
的初始值CURRENT_ROLE ()
反映新的默认角色分配:
mysql >选择CURRENT_ROLE ();+--------------------------------+ | CURRENT_ROLE () | +--------------------------------+ | ` app_read ' @ ' % ', ' app_write `@`%` | +--------------------------------+
要使所有显式授予的和强制的角色在用户连接到服务器时自动激活,请启用activate_all_roles_on_login
系统变量。缺省情况下,角色自动激活处于关闭状态。
在会话中,用户可以执行设置角色
更改活动角色集。例如,对于rw_user1
:
SET ROLE NONE;选择CURRENT_ROLE ();+----------------+ | CURRENT_ROLE () | +----------------+ | 没有一个 | +----------------+ mysql >设置角色除了“app_write”;选择CURRENT_ROLE ();+----------------+ | CURRENT_ROLE () | +----------------+ | ` app_read `@`%` | +----------------+ mysql >设置角色默认;选择CURRENT_ROLE ();+--------------------------------+ | CURRENT_ROLE () | +--------------------------------+ | ` app_read ' @ ' % ', ' app_write `@`%` | +--------------------------------+
第一个设置角色
语句将禁用所有角色。第二个让rw_user1
有效的阅读。第三个恢复默认角色。
存储程序和视图对象的有效用户受定义者
而且SQL安全
属性,这些属性确定执行是发生在调用程序上下文中还是定义器上下文中(参见第25.6节,“存储对象访问控制”):
在调用程序上下文中执行的存储程序和视图对象与当前会话中活动的角色一起执行。
在definer上下文中执行的存储程序和视图对象使用它们中命名的用户的默认角色执行
定义者
属性。如果activate_all_roles_on_login
启用时,这些对象执行时将所有角色授予定义者
用户,包括必选角色。对于存储程序,如果执行的角色与默认角色不同,则应该执行程序主体设置角色
激活所需的角色。
就像角色可以被授予帐户一样,它们也可以从帐户中被撤销:
撤销角色从用户;
中命名的角色mandatory_roles
系统变量值不能被撤销。
撤销
还可以应用于角色以修改授予它的特权。这不仅会影响角色本身,还会影响授予该角色的任何帐户。假设您希望临时将所有应用程序用户设置为只读。要做到这一点,使用撤销
控件的修改权限app_write
角色:
取消app_db上的插入、更新、删除操作。*“app_write”;
当它发生时,这使得角色没有任何特权,正如可以看到的使用秀奖助金
(这说明该语句可以用于角色,而不仅仅是用户):
mysql> SHOW grant FOR app_write;+---------------------------------------+ | 资助app_write @% | +---------------------------------------+ | 格兰特使用*。*“app_write `@`%` | +---------------------------------------+
因为从角色中撤销权限会影响分配了修改后的角色的任何用户的权限,rw_user1
现在没有表修改权限(插入
,更新
,删除
不再存在):
mysql> SHOW grant FOR 'rw_user1'@'localhost' USING 'app_read', 'app_write';+----------------------------------------------------------------+ | 资助rw_user1@localhost | +----------------------------------------------------------------+ | 格兰特使用*。对于' rw_user1 ' @ ' localhost ' | |授予SELECT ' app_db '*“rw_user1”@“localhost”| |授予“app_read”@“%”,“app_write”@“%”“rw_user1”@ localhost ` | +----------------------------------------------------------------+
实际上,rw_user1
读写用户变成只读用户。权限授予的任何其他帐户也会发生这种情况app_write
角色,说明了使用角色如何使无需修改单个帐户的特权。
要恢复角色的修改权限,只需重新授予它们:
授予app_db的插入、更新、删除权限。*“app_write”;
现在rw_user1
具有修改权限,与授予的任何其他帐户一样app_write
的角色。
要删除角色,请使用下降的作用
:
删除'app_read', 'app_write';
删除一个角色将从每个被授予该角色的帐户中撤销该角色。
中命名的角色mandatory_roles
不能删除系统变量值。
正如前面所暗示的秀奖助金
,其中显示用户帐户或角色的授权,帐户和角色可以互换使用。
角色和用户之间的一个区别是创建角色
创建默认锁定的授权标识符,而创建用户
创建默认情况下未锁定的授权标识符。但是,区别并不是不可变的,因为具有适当特权的用户可以在创建角色或用户后锁定或解锁角色或用户。
如果数据库管理员希望特定的授权标识符必须是角色,则可以使用名称方案来传达这一意图。例如,你可以用ar_
您希望作为角色的所有授权标识符的前缀,而没有其他。
角色和用户之间的另一个区别在于可用于管理它们的特权:
因此,创建角色
而且下降的作用
特权没有特权那么强大创建用户
和可以授予只允许创建和删除角色,而不允许执行更一般的帐户操作的用户。
关于用户和角色的特权和互换性,您可以将用户帐户视为角色,并将该帐户授予另一个用户或角色。其结果是将帐户的特权和角色授予其他用户或角色。
这组语句演示了可以将用户授予用户,将角色授予用户,将用户授予角色,或将角色授予角色:
创建用户‘u1’;创建角色“r1”;在db1上授予SELECT权限。*“u1”;在db2上授予SELECT权限。*“r1”;创建用户“u2”;创建角色的r2;GRANT 'u1', 'r1' TO 'u2';GRANT 'u1', 'r1' TO 'r2';
每种情况下的结果都是将与被授予对象相关联的特权授予被授予对象。在执行这些语句之后,每一个u2
而且r2
已从用户(u1
)和角色(r1
):
mysql> SHOW grant FOR 'u2' USING 'u1', 'r1';+-------------------------------------+ | 授予对u2 @% | +-------------------------------------+ | 格兰特使用*。TO ' u2 ' @ ' % ' | | GRANT SELECT ON ' db1 'TO ' u2 ' @ ' % ' | | GRANT SELECT ON ' db2 '。*“u2 `@`%` | | 授予“u1”@“%”,“r1”@“%”“u2 `@`%` | +-------------------------------------+ mysql >显示赠款的r2使用‘u1’,‘r1’;+-------------------------------------+ | r2的资助 @% | +-------------------------------------+ | 格兰特使用*。*对' r2 ' @ ' % ' | |授权SELECT ' db1 'TO ' r2 ' @ ' % ' | | GRANT SELECT ' db2 '*“r2 `@`%` | | 授予“u1”@“%”,“r1”@“%”“r2 `@`%` | +-------------------------------------+
前面的例子只是说明性的,但是用户帐户和角色的互换性有实际的应用,例如在以下情况中:假设一个遗留应用程序开发项目在MySQL中出现角色之前就开始了,因此与该项目相关的所有用户帐户都直接被授予特权(而不是通过被授予角色来授予特权)。其中一个帐户是开发人员帐户,最初被授予如下特权:
CREATE USER 'old_app_dev'@'localhost' IDENTIFIED BY 'old_app_devpass';在old_app上授予所有权限。*“old_app_dev”@“localhost”;
如果这个开发人员离开了项目,就有必要将特权分配给另一个用户,或者如果开发活动扩展了,可能会分配给多个用户。这里有一些处理这个问题的方法:
不使用角色:更改帐户密码,使原来的开发人员不能使用它,并让新的开发人员使用该帐户:
ALTER USER 'old_app_dev'@'localhost' IDENTIFIED BY 'new_password”;
使用角色:锁定帐户,防止任何人使用该帐户连接到服务器:
ALTER USER 'old_app_dev'@'localhost' ACCOUNT LOCK
然后将该帐户视为一个角色。对于每个新加入项目的开发人员,创建一个新帐户,并授予它原来的开发人员帐户:
创建用户new_app_dev1 @ localhostnew_password”;GRANT 'old_app_dev'@'localhost' TO 'new_app_dev1'@'localhost';
其结果是将原始开发人员帐户特权分配给新帐户。