文档首页
MySQL 9.0 参考手册
相关文档 下载本手册

MySQL 9.0 参考手册  /  ...  /  帐户类别

8.2.11 帐户类别

MySQL 结合了用户帐户类别的概念,该概念基于 SYSTEM_USER 权限。

系统帐户和普通帐户

MySQL 结合了用户帐户类别的概念,系统用户和普通用户根据其是否具有 SYSTEM_USER 权限来区分。

SYSTEM_USER 权限会影响给定用户可以对其其他权限应用的帐户,以及该用户是否受其他帐户的保护。

  • 系统用户可以修改系统帐户和普通帐户。也就是说,如果用户拥有对普通帐户执行给定操作的适当权限,则拥有 SYSTEM_USER 权限的用户也可以对系统帐户执行该操作。系统帐户只能由具有适当权限的系统用户修改,而不能由普通用户修改。

  • 具有适当权限的普通用户可以修改普通帐户,但不能修改系统帐户。普通帐户可以由具有适当权限的系统用户和普通用户修改。

如果用户拥有对普通帐户执行给定操作的适当权限,则 SYSTEM_USER 权限将允许该用户也对系统帐户执行该操作。SYSTEM_USER 权限并不意味着任何其他权限,因此执行给定帐户操作的能力仍然取决于拥有任何其他所需的权限。例如,如果用户可以向普通帐户授予 SELECTUPDATE 权限,则拥有 SYSTEM_USER 权限的用户也可以向系统帐户授予 SELECTUPDATE 权限。

系统帐户和普通帐户之间的区别可以通过保护具有 SYSTEM_USER 权限的帐户免遭没有该权限的帐户的攻击,从而更好地控制某些帐户管理问题。例如,CREATE USER 权限不仅可以创建新帐户,还可以修改和删除现有帐户。如果没有系统用户的概念,则拥有 CREATE USER 权限的用户可以修改或删除任何现有帐户,包括 root 帐户。系统用户的概念可以限制对 root 帐户(本身就是一个系统帐户)的修改,使其只能由系统用户进行。具有 CREATE USER 权限的普通用户仍然可以修改或删除现有帐户,但只能修改或删除普通帐户。

受 SYSTEM_USER 权限影响的操作

SYSTEM_USER 权限会影响以下操作:

  • 帐户操作。

    帐户操作包括创建和删除帐户、授予和撤销权限、更改帐户身份验证特征(如凭据或身份验证插件)以及更改其他帐户特征(如密码过期策略)。

    要使用 CREATE USERGRANT 等账户管理语句操作系统账户,需要 SYSTEM_USER 权限。要防止账户以这种方式修改系统账户,请不要为其授予 SYSTEM_USER 权限,使其成为普通账户。(但是,要完全保护系统账户免受普通账户的攻击,还必须拒绝为普通账户授予对 mysql 系统数据库的修改权限。请参阅 防止系统账户被普通账户操作。)

  • 终止当前会话以及在其中执行的语句。

    要终止使用 SYSTEM_USER 权限执行的会话或语句,您自己的会话除了需要任何其他必需的权限(CONNECTION_ADMIN 或已弃用的 SUPER 权限)外,还必须拥有 SYSTEM_USER 权限。

    如果将服务器置于离线模式的用户没有 SYSTEM_USER 权限,则拥有 SYSTEM_USER 权限的已连接客户端用户也不会断开连接。但是,除非这些用户还拥有 CONNECTION_ADMINSUPER 权限,否则他们无法在服务器处于离线模式时发起与服务器的新连接。只有他们现有的连接不会终止,因为终止连接需要 SYSTEM_USER 权限。

  • 设置存储对象的 DEFINER 属性。

    要将存储对象的 DEFINER 属性设置为拥有 SYSTEM_USER 权限的账户,除了任何其他必需的权限外,您还必须拥有 SYSTEM_USER 权限。

  • 指定强制角色。

    拥有 SYSTEM_USER 权限的角色不能列在 mandatory_roles 系统变量的值中。

  • 覆盖 MySQL Enterprise Audit 的审计日志过滤器中的“abort”项。

    拥有 SYSTEM_USER 权限的账户会自动被分配 AUDIT_ABORT_EXEMPT 权限,以便即使审计日志过滤器中的“abort”项会阻止来自该账户的查询,也会始终执行这些查询。因此,在审计配置错误后,可以使用拥有 SYSTEM_USER 权限的账户重新获得对系统的访问权限。请参阅 第 8.4.5 节 “MySQL Enterprise Audit”

系统会话和普通会话

在服务器中执行的会话区分为系统会话或普通会话,类似于系统用户和普通用户之间的区别

普通会话只能执行允许普通用户执行的操作。系统会话还可以执行仅允许系统用户执行的操作。

会话拥有的权限是直接授予其基础账户的权限,以及授予会话中当前处于活动状态的所有角色的权限。因此,会话可能是系统会话,因为其账户已被直接授予 SYSTEM_USER 权限,或者因为该会话已激活具有 SYSTEM_USER 权限的角色。授予账户但未在会话中激活的角色不会影响会话权限。

因为激活和停用角色会更改会话拥有的权限,所以会话可能会从普通会话更改为系统会话,反之亦然。如果会话激活或停用了具有 SYSTEM_USER 权限的角色,则仅针对该会话立即进行普通会话和系统会话之间的相应更改

  • 如果普通会话激活了具有 SYSTEM_USER 权限的角色,则该会话将变为系统会话。

  • 如果系统会话停用了具有 SYSTEM_USER 权限的角色,则该会话将变为普通会话,除非具有 SYSTEM_USER 权限的其他角色仍处于活动状态。

这些操作对现有会话没有影响

  • 如果向账户授予或撤销 SYSTEM_USER 权限,则该账户的现有会话不会在普通会话和系统会话之间更改。授予或撤销操作仅影响该账户后续连接的会话。

  • 由会话中调用的存储对象执行的语句使用父会话的系统或常规状态执行,即使该对象 DEFINER 属性命名了系统账户也是如此。

因为角色激活仅影响会话而不影响账户,所以将具有 SYSTEM_USER 权限的角色授予普通账户并不能保护该账户免受普通用户的攻击。该角色仅保护该账户中已激活该角色的会话,并且仅保护该会话免受普通会话的终止。

防止系统账户被普通账户操作

帐户操作包括创建和删除帐户、授予和撤销权限、更改帐户身份验证特征(如凭据或身份验证插件)以及更改其他帐户特征(如密码过期策略)。

可以通过两种方式进行账户操作

  • 通过使用 CREATE USERGRANT 等账户管理语句。这是首选方法。

  • 通过使用 INSERTUPDATE 等语句直接修改授权表。不鼓励使用此方法,但对于对包含授权表的 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 数据库,例如只读访问。以下示例创建了一个账户,该账户对所有数据库都具有全局 SELECTINSERTUPDATEDELETE 权限,但对 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 进行部分撤销,也可以这样做。以下语句允许对 u1 进行 mysql 数据库内的只读访问,但仅限于 db 表以及 user 表的 HostUser

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;