账户类型
从MySQL 8.0.16开始,MySQL引入了基于 SYSTEM_USER
用户权限的用户帐户类别概念。
系统和常规账户
MySQL 引入了用户帐户类别的概念,根据是否具有 SYSTEM_USER
权限来区分系统用户和普通用户:
- 具有
SYSTEM_USER
权限的用户是系统用户。 - 没有
SYSTEM_USER
权限的用户是普通用户。
受 SYSTEM_USER 权限影响的操作
SYSTEM_USER
权限会影响这些操作:
-
账户操作。帐户操作包括创建和删除帐户、授予和撤消权限、更改帐户身份验证特征(如凭据或身份验证插件)以及更改其他帐户特征(如密码过期策略)。使用帐户管理语句(如
CREATE USER
和GRANT
)操作系统帐户需要SYSTEM_USER
权限。要防止帐户以这种方式修改系统帐户,请将其设置为普通帐户,不要授予它SYSTEM_USER
权限。 -
正在终止当前会话和其中执行的语句。要终止以
SYSTEM_USER
权限执行的会话或语句,除了任何其他必需的权限之外,您自己的会话还必须具有SYSTEM_USER
权限。 -
设置存储对象的
DEFINER
属性。要将存储对象的DEFINER
属性设置为具有SYSTEM_USER
权限的帐户,您必须拥有SYSTEM_USER
权限,以及任何其他必需的权限 -
指定强制角色。具有
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
权限或撤销该帐户的SYSTEM_USER
权限,则该帐户的现有会话不会在常规会话和系统会话之间更改。授予或撤销操作只影响该帐户后续连接的会话。
因为角色激活只影响会话而不影响帐户,所以将具有SYSTEM_USER
权限的角色授予普通帐户并不能保护该帐户不受普通用户的攻击。该角色仅保护已激活该角色的帐户的会话,并且仅保护会话不被常规会话终止。
保护系统帐户免受常规帐户的操作
帐户操作包括创建和删除帐户、授予和撤销权限、更改帐户身份验证特征(如凭据或身份验证插件)以及更改其他帐户特征。
帐户操作可以通过两种方式完成:
- 通过使用帐户管理语句,例如
CREATE USER
和GRANT
。这是首选方法。 - 通过使用
INSERT
和UPDATE
等语句直接授权表修改。不建议使用这种方法
要完全保护系统帐户免受给定帐户的修改,请将其设置为常规帐户,并且不要为其授予 mysql schema修改权限:
-
使用帐户管理语句操作系统帐户需要
SYSTEM_USER
权限。要防止帐户以这种方式修改系统帐户,可以将其设置为普通帐户,不授予SYSTEM_USER
权限 -
mysql schema的权限允许通过直接修改授予表来操作系统帐户,即使修改帐户是一个普通帐户。为了限制普通帐户对系统帐户未经授权的直接修改,不要将mysql schema的修改权限授予该帐户(或授予该帐户的任何角色)。如果一个普通帐户必须拥有适用于所有schema的全局权限,mysql schema修改可以通过使用部分撤销的权限限制来阻止。
假设您希望创建一个用户u1
,该用户拥有所有schemas上的所有权限,但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
的schema,请撤销其对 mysql
的schema的所有权限,如刚才所示。也可以允许部分 mysql
的schema被访问,例如只读访问。以下示例创建一个帐户,该帐户对所有schema具有全局 SELECT、INSERT、UPDATE
和 DELET
权限,但对 mysql
的schema仅具有 SELECT
权限:
CREATE USER u2 IDENTIFIED BY 'password';
GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO u2;
REVOKE INSERT, UPDATE, DELETE ON mysql.* FROM u2;
另一种可能性是撤销所有 mysql
的schema的权限,但授予对特定 mysql
表或列的访问权限。
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;