MySQL 基于 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
权限会影响以下操作:
-
帐户操作。
帐户操作包括创建和删除帐户、授予和撤销权限、更改帐户身份验证特性(例如凭据或身份验证插件),以及更改其他帐户特性(例如密码过期策略)。
要使用账户管理语句(例如
CREATE USER
和GRANT
)操作系统账户,需要SYSTEM_USER
权限。要防止某个账户以此方式修改系统账户,请不要授予它SYSTEM_USER
权限,将其设为常规账户。(但是,要完全保护系统账户免受常规账户的影响,还必须拒绝常规账户对mysql
系统架构的修改权限。请参见 保护系统账户免受常规账户的操作。) -
终止当前会话以及在其中执行的语句。
要终止使用
SYSTEM_USER
权限执行的会话或语句,您自己的会话除了任何其他必需的权限(CONNECTION_ADMIN
或已弃用的SUPER
权限)之外,还必须具有SYSTEM_USER
权限。如果将服务器置于离线模式的用户没有
SYSTEM_USER
权限,则具有SYSTEM_USER
权限的已连接客户端用户也不会断开连接。但是,除非这些用户还具有CONNECTION_ADMIN
或SUPER
权限,否则他们在服务器处于离线模式时无法启动与服务器的新连接。只有他们现有的连接不会终止,因为这需要SYSTEM_USER
权限。 -
为存储对象设置
DEFINER
属性。要将存储对象的
DEFINER
属性设置为具有SYSTEM_USER
权限的账户,除了任何其他必需的权限(SET_USER_ID
或已弃用的SUPER
权限)之外,您还必须具有SYSTEM_USER
权限。 -
指定强制角色。
具有
SYSTEM_USER
权限的角色不能在mandatory_roles
系统变量的值中列出。 -
覆盖 MySQL Enterprise Audit 审计日志过滤器中的 “中止” 项。
拥有
SYSTEM_USER
权限的账户会自动分配AUDIT_ABORT_EXEMPT
权限,以便即使审计日志过滤器中的 “中止” 项会阻止该账户的查询,这些查询也会始终执行。因此,拥有SYSTEM_USER
权限的账户可用于在审计配置错误后重新获得对系统的访问权限。参见 第 8.4.5 节,“MySQL Enterprise Audit”。
在服务器内执行的会话分为系统会话和常规会话,类似于系统用户和常规用户之间的区别:
-
拥有
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
架构修改。请参见 第 8.2.12 节,“使用部分撤销进行权限限制”。
与拒绝授予 SYSTEM_USER
权限不同,后者会阻止账户修改系统账户但不会阻止修改普通账户,而拒绝授予 mysql
架构权限则会阻止账户修改系统账户和普通账户。这应该不成问题,因为如前所述,不鼓励直接修改授权表。
假设您要创建一个用户 u1
,该用户对所有架构都拥有所有权限,但 u1
应该是一个没有修改系统账户能力的普通用户。假设 partial_revokes
系统变量已启用,请按如下方式配置 u1
:
CREATE USER u1 IDENTIFIED BY 'password';
GRANT ALL ON *.* TO u1 WITH GRANT OPTION;
-- GRANT ALL includes SYSTEM_USER, so at this point
-- u1 can manipulate system or regular accounts
REVOKE SYSTEM_USER ON *.* FROM u1;
-- Revoking SYSTEM_USER makes u1 a regular user;
-- now u1 can use account-management statements
-- to manipulate only regular accounts
REVOKE 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
权限的账户,但对 mysql
架构只有 SELECT
权限:
CREATE USER u2 IDENTIFIED BY 'password';
GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO u2;
REVOKE INSERT, UPDATE, DELETE ON mysql.* FROM u2;
另一种可能性是撤销所有 mysql
架构权限,但授予对特定 mysql
表或列的访问权限。即使对 mysql
进行部分撤销,也可以这样做。以下语句允许在 mysql
架构内对 u1
进行只读访问,但仅限于 db
表以及 user
表的 Host
和 User
列:
CREATE USER u3 IDENTIFIED BY 'password';
GRANT ALL ON *.* TO u3;
REVOKE ALL ON mysql.* FROM u3;
GRANT SELECT ON mysql.db TO u3;
GRANT SELECT(Host,User) ON mysql.user TO u3;