帐户类别
从MySQL 8.0.16开始,MySQL结合了基于SYSTEM_USER
特权的用户帐户类别的概念。
- 系统帐户和常规帐户
- 受SYSTEM_USER特权影响的操作
- 系统会议和例会
- 保护系统帐户不被常规帐户操纵
系统帐户和常规帐户
MySQL结合了用户帐户类别的概念,根据系统用户和普通用户是否具有SYSTEM_USER
特权来区分它们:
- 具有
SYSTEM_USER
特权的用户是系统用户。 - 没有
SYSTEM_USER
特权的用户是普通用户。
在SYSTEM_USER
特权上,给定用户可以应用其其他特权,以及用户是否从其他帐户保护的帐户的效果:
- 系统用户可以修改系统帐户和普通帐户。即,具有拥有对普通帐户执行给定操作的权限的用户通过拥有
SYSTEM_USER
还对系统帐户执行操作而被启用。系统帐户只能由具有适当特权的系统用户修改,而不能由普通用户修改。 - 具有适当特权的普通用户可以修改普通帐户,但不能修改系统帐户。普通帐户可以由具有适当特权的系统用户和普通用户修改。
如果用户具有对常规帐户执行给定操作的适当特权,则SYSTEM_USER
使用户也可以对系统帐户执行操作。SYSTEM_USER
并不意味着任何其他特权,因此执行给定帐户操作的能力仍然取决于是否拥有其他任何必需的特权。例如,如果用户可以授予SELECT
和UPDATE
权限定期帐户,然后SYSTEM_USER
用户还可以授予SELECT
和UPDATE
系统帐户。
系统帐户和常规帐户之间的区别可以通过保护具有SYSTEM_USER
特权的帐户与没有特权的帐户来更好地控制某些帐户管理问题。例如,CREATE USER
特权不仅可以创建新帐户,还可以修改和删除现有帐户。没有系统用户概念,具有CREATE USER
特权的用户可以修改或删除任何现有帐户,包括该root
帐户。系统用户的概念允许限制对root
帐户(本身是系统帐户)的修改,因此只能由系统用户进行修改。普通用户CREATE USER
特权仍然可以修改或删除现有帐户,但只能修改或删除常规帐户。
受SYSTEM_USER特权影响的操作
该SYSTEM_USER
特权影响这些操作:
帐户操作。
帐户操作包括创建和删除帐户,授予和撤销特权,更改帐户身份验证特征(例如凭据或身份验证插件)以及更改其他帐户特征(例如密码到期策略)。
该
SYSTEM_USER
权限需要使用账户管理语句,如操纵系统帐户CREATE USER
和GRANT
。为防止帐户以这种方式修改系统帐户,请通过不授予其SYSTEM_USER
特权来使其成为普通帐户。(但是,要完全保护系统帐户免受常规帐户的侵害,还必须mysql
从常规帐户中保留对系统架构的修改特权。请参阅保护系统帐户免受常规帐户的操纵。)终止当前会话和在其中执行的语句。
要杀死使用该
SYSTEM_USER
特权执行的会话或语句,SYSTEM_USER
除了任何其他必需的特权(CONNECTION_ADMIN
或SUPER
)之外,您自己的会话还必须具有该特权。在MySQL 8.0.16之前,
CONNECTION_ADMIN
还是SUPER
足以杀死任何会话或语句。设置
DEFINER
存储对象。要将
DEFINER
存储对象的属性设置为具有SYSTEM_USER
特权的帐户,SYSTEM_USER
除了必须具有任何其他必需的特权(SET_USER_ID
或SUPER
)之外,还必须具有该特权。在MySQL 8.0.16之前,
SET_USER_ID
还是SUPER
足以DEFINER
为存储的对象指定任何值。指定强制角色。
具有
SYSTEM_USER
特权的角色无法在mandatory_roles
系统变量的值中列出。在MySQL 8.0.16之前,任何角色都可以在中列出
mandatory_roles
。
系统会议和例会
服务器中执行的会话被区分为系统会话还是常规会话,类似于系统用户和常规用户之间的区别:
- 拥有
SYSTEM_USER
特权的会话是系统会话。 - 不具有
SYSTEM_USER
特权的会话是常规会话。
常规会话只能执行常规用户允许的操作。系统会话还能够执行仅允许系统用户使用的操作。
会话拥有的特权是直接授予其基础帐户的特权,以及授予该会话中当前活动的所有角色的特权。因此,会话可能是系统会话,因为它的帐户已被SYSTEM_USER
直接授予特权,或者因为该会话已激活具有该SYSTEM_USER
特权的角色。授予帐户的在会话中未激活的角色不会影响会话特权。
因为激活和停用角色可以更改会话拥有的特权,所以会话可以从常规会话更改为系统会话,反之亦然。如果会话激活或取消激活具有SYSTEM_USER
特权的角色,则仅针对该会话,立即在常规会话和系统会话之间进行适当的更改:
- 如果常规会话使用
SYSTEM_USER
特权激活角色,则该会话将成为系统会话。 - 如果系统会话停用具有
SYSTEM_USER
特权的角色,则该会话将变为常规会话,除非具有该SYSTEM_USER
特权的某些其他角色保持活动状态。
这些操作对现有会话没有影响:
- 如果
SYSTEM_USER
授予或撤消了该特权,则该帐户的现有会话在常规会话和系统会话之间不会更改。授予或撤消操作仅影响该帐户的后续连接会话。 - 由会话内调用的存储对象执行的语句以父会话的系统状态或常规状态执行,即使对象
DEFINER
属性为系统帐户命名。
由于角色激活仅影响会话,而不影响帐户,因此将具有SYSTEM_USER
特权的角色授予常规帐户不会保护该帐户免受常规用户的侵害。该角色仅保护已激活该角色的帐户的会话,并且仅保护该会话以防止被常规会话杀死。
保护系统帐户不被常规帐户操纵
帐户操作包括创建和删除帐户,授予和撤销特权,更改帐户身份验证特征(例如凭据或身份验证插件)以及更改其他帐户特征(例如密码到期策略)。
帐户操作可以通过两种方式完成:
- 通过使用诸如
CREATE USER
和的帐户管理对帐单GRANT
。这是首选方法。 - 通过使用诸如
INSERT
和的语句直接修改授予表UPDATE
。不鼓励使用此方法,但对于在mysql
包含授权表的系统架构上具有适当特权的用户而言,此方法是可行的。
要完全保护系统帐户免受给定帐户的修改,请使其成为普通帐户,并且不授予其mysql
架构的修改特权:
- 该
SYSTEM_USER
权限才能操作使用账户管理报表系统帐户。为防止帐户以这种方式修改系统帐户,请通过不授予SYSTEM_USER
该帐户的权限将其设置为常规帐户。这包括不授予SYSTEM_USER
授予该帐户的任何角色。 mysql
模式的特权允许通过直接修改授权表来操纵系统帐户,即使修改帐户是普通帐户也是如此。要限制常规帐户对系统帐户的未经授权的直接修改,请不要mysql
向该帐户(或授予该帐户的任何角色)授予架构的修改特权。如果普通帐户必须具有适用于所有架构的全局特权,mysql
则可以通过使用部分吊销施加的特权限制来防止架构修改。请参见“使用部分撤销的权限限制”。
注意与保留
SYSTEM_USER
特权(阻止帐户修改系统帐户而不是常规帐户)不同,保留mysql
模式特权可以阻止帐户修改系统帐户和常规帐户。如前所述,这不应该成为问题,因为不建议直接修改授予表。
假设您要创建一个u1
对所有模式都具有所有特权的用户,但该u1
用户应该是没有修改系统帐户能力的普通用户。假设partial_revokes
已启用系统变量,请进行以下配置u1
:
CREATE USER u1IDENTIFIED BY 'password';GRANT ALL ON *.*TO u1WITH GRANT OPTION ; -- GRANT ALL includes SYSTEM_USER, so at this point -- u1 can manipulate system or regular accountsREVOKE SYSTEM_USERON *.*FROM u1; -- Revoking SYSTEM_USER makes u1 a regular user; -- now u1 can use account-management statements -- to manipulate only regular accountsREVOKE ALL ON mysql.*FROM u1; -- This partial revoke prevents u1 from directly -- modifying grant tables to manipulate accounts
为了防止mysql
某个帐户对所有系统架构的访问,请取消对mysql
架构的所有特权,如下所示。也可以允许部分mysql
模式访问,例如只读访问。下面的示例创建具有一个帐户SELECT
,INSERT
,UPDATE
,和DELETE
特权全球范围内为所有的模式,但只SELECT
为mysql
模式:
CREATE USER u2IDENTIFIED BY 'password';GRANT SELECT ,INSERT ,UPDATE ,DELETE ON *.*TO u2;REVOKE INSERT ,UPDATE ,DELETE ON mysql.*FROM u2;
另一种可能性是撤销所有mysql
架构特权,但授予对特定mysql
表或列的访问权限。即使部分撤消,也可以完成此操作mysql
。以下语句启用u1
对mysql
架构内的只读访问,但仅对db
表以及表的Host
和User
列启用user
:
CREATE USER u3IDENTIFIED BY 'password';GRANT ALL ON *.*TO u3;REVOKE ALL ON mysql.*FROM u3;GRANT SELECT ON mysql.dbTO u3;GRANT SELECT (Host ,User )ON mysql.user TO u3;