MySQL8 中文参考(二十四)(1)https://developer.aliyun.com/article/1566152
SENSITIVE_VARIABLES_OBSERVER
(在 MySQL 8.0.29 中添加)
允许持有者查看性能模式表中敏感系统变量的值global_variables
,session_variables
,variables_by_thread
,和persisted_variables
,发出SELECT
语句以返回它们的值,并在会话跟踪器中跟踪连接的更改。没有此权限的用户无法查看或跟踪这些系统变量的值。请参见持久化敏感系统变量。SERVICE_CONNECTION_ADMIN
允许连接到仅允许管理连接的网络接口(参见第 7.1.12.1 节,“连接接口”)。SESSION_VARIABLES_ADMIN
(在 MySQL 8.0.14 中添加)
对于大多数系统变量,设置会话值不需要特殊权限,任何用户都可以执行以影响当前会话。对于一些系统变量,设置会话值可能会影响当前会话之外的效果,因此是一项受限操作。对于这些情况,SESSION_VARIABLES_ADMIN
权限使用户能够设置会话值。
如果系统变量受限并需要特殊权限来设置会话值,则变量描述会指示该限制。例如包括binlog_format
,sql_log_bin
,和sql_log_off
。
在 MySQL 8.0.14 之前,当添加了SESSION_VARIABLES_ADMIN
时,受限会话系统变量只能由具有SYSTEM_VARIABLES_ADMIN
或SUPER
权限的用户设置。SESSION_VARIABLES_ADMIN
特权是SYSTEM_VARIABLES_ADMIN
和SUPER
特权的子集。拥有这些特权之一的用户也被允许设置受限制的会话变量,并且通过暗示具有SESSION_VARIABLES_ADMIN
,无需显式授予SESSION_VARIABLES_ADMIN
。
另请参阅第 7.1.9.1 节,“系统变量特权”。SET_USER_ID
允许在执行视图或存储程序时设置有效的授权 ID。拥有此特权的用户可以将任何帐户指定为视图或存储程序的DEFINER
属性。存储程序将以指定帐户的权限执行,因此请确保遵循第 27.6 节,“存储对象访问控制”中列出的风险最小化准则。
截至 MySQL 8.0.22,SET_USER_ID
还允许覆盖旨在防止(可能是无意的)导致存储对象变成孤立或导致当前孤立的存储对象被采用的安全检查。有关详细信息,请参阅孤立存储对象。SHOW_ROUTINE
(MySQL 8.0.20 中添加)允许用户访问所有存储例程(存储过程和函数)的定义和属性,即使用户未被命名为例程的DEFINER
。此访问权限包括:
- 信息模式
ROUTINES
表的内容。 SHOW CREATE FUNCTION
和SHOW CREATE PROCEDURE
语句。SHOW FUNCTION CODE
和SHOW PROCEDURE CODE
语句。SHOW FUNCTION STATUS
和SHOW PROCEDURE STATUS
语句。
- 在 MySQL 8.0.20 之前,用户要访问未定义的例程的定义,用户必须拥有全局
SELECT
权限,这是非常广泛的。从 8.0.20 开始,可以授予SHOW_ROUTINE
权限,这是一个范围更受限制的权限,允许访问例程定义。(也就是说,管理员可以从不需要的用户那里撤销全局SELECT
并授予SHOW_ROUTINE
)。这使得一个账户可以备份存储例程而不需要广泛的权限。 SKIP_QUERY_REWRITE
(MySQL 8.0.31 中添加)
拥有此权限的用户发出的查询不会被Rewriter
插件重写(参见第 7.6.4 节,“Rewriter 查询重写插件”)。
此权限应授予发出不应被重写的管理或控制语句的用户,以及用于应用来自复制源的语句的PRIVILEGE_CHECKS_USER
账户(参见第 19.3.3 节,“复制权限检查”)。SYSTEM_USER
(MySQL 8.0.16 中添加)SYSTEM_USER
权限区分系统用户和普通用户:
- 拥有
SYSTEM_USER
权限的用户是系统用户。 - 没有
SYSTEM_USER
权限的用户是普通用户。
SYSTEM_USER
权限影响用户可以应用其它权限的账户,以及用户是否受到其他账户的保护:
- 系统用户可以修改系统账户和普通账户。也就是说,拥有在普通账户上执行特定操作的适当权限的用户,通过拥有
SYSTEM_USER
权限也可以在系统账户上执行该操作。只有拥有适当权限的系统用户才能修改系统账户,普通用户无法修改。 - 拥有适当权限的普通用户可以修改普通账户,但不能修改系统账户。系统账户可以被拥有适当权限的系统用户和普通用户修改。
- 这也意味着,由拥有
SYSTEM_USER
权限的用户创建的数据库对象不能被没有该权限的用户修改或删除。对于定义者拥有此权限的例程也适用。
更多信息,请参见第 8.2.11 节,“账户类别”。
由于SYSTEM_USER
权限为系统帐户提供的修改保护不适用于具有对mysql
系统模式特权的常规帐户,因此可以直接修改该模式中的授权表。为了完全保护,请不要向常规帐户授予mysql
模式特权。请参见防止常规帐户操纵系统帐户。
如果使用了audit_log
插件(参见第 8.4.5 节,“MySQL 企业审计”),从 MySQL 8.0.28 开始,具有SYSTEM_USER
权限的帐户将自动被分配AUDIT_ABORT_EXEMPT
权限,允许他们的查询即使在过滤器中配置了“中止”项目也能执行。具有SYSTEM_USER
权限的帐户因此可用于在审计配置错误后恢复对系统的访问。 SYSTEM_VARIABLES_ADMIN
影响以下操作和服务器行为:
- 允许在运行时更改系统变量:
- 允许使用
SET GLOBAL
和SET PERSIST
对全局系统变量进行服务器配置更改。 - 允许使用
SET PERSIST_ONLY
对全局系统变量进行服务器配置更改,如果用户还具有PERSIST_RO_VARIABLES_ADMIN
权限。 - 允许设置需要特殊权限的受限会话系统变量。实际上,
SYSTEM_VARIABLES_ADMIN
意味着未明确授予SESSION_VARIABLES_ADMIN
。
- 另请参阅第 7.1.9.1 节,“系统变量权限”。
- 允许更改全局事务特性(参见第 15.3.7 节,“SET TRANSACTION 语句”)。
TABLE_ENCRYPTION_ADMIN
(在 MySQL 8.0.16 中添加)
当启用table_encryption_privilege_check
时,允许用户覆盖默认加密设置;参见为模式和通用表空间定义加密默认值。TELEMETRY_LOG_ADMIN
启用遥测日志配置。此特权由部署在 AWS 上的 MySQL HeatWave 的telemetry_log
插件定义。TP_CONNECTION_ADMIN
允许使用特权连接连接到服务器。当达到由thread_pool_max_transactions_limit
定义的限制时,不允许新连接。特权连接忽略事务限制,并允许连接到服务器以增加事务限制、移除限制或终止运行中的事务。此特权不会默认授予任何用户。要建立特权连接,发起连接的用户必须具有TP_CONNECTION_ADMIN
特权。
当达到由thread_pool_max_transactions_limit
定义的限制时,特权连接可以执行语句并启动事务。特权连接被放置在Admin
线程组中。参见特权连接。VERSION_TOKEN_ADMIN
允许执行版本令牌函数。此特权由version_tokens
插件定义;参见第 7.6.6 节,“版本令牌”。XA_RECOVER_ADMIN
允许执行XA RECOVER
语句;参见第 15.3.8.1 节,“XA 事务 SQL 语句”。
在 MySQL 8.0 之前,任何用户都可以执行XA RECOVER
语句来发现未完成的准备好的 XA 事务的 XID 值,可能导致由非启动者执行提交或回滚 XA 事务。在 MySQL 8.0 中,XA RECOVER
仅允许拥有XA_RECOVER_ADMIN
权限的用户执行,这个权限预期只授予有需要的管理用户。例如,如果 XA 应用程序崩溃并且需要找到应用程序启动的未完成事务以便回滚,那么可能会出现这种情况。这种权限要求阻止用户发现除自己之外的未完成准备好的 XA 事务的 XID 值。它不会影响 XA 事务的正常提交或回滚,因为启动它的用户知道它的 XID。
权限授予指南
为账户授予它所需的权限是一个好主意。在授予 FILE
和管理权限时应特别小心:
FILE
可以被滥用来读取 MySQL 服务器在服务器主机上可以读取的任何文件到数据库表中。这包括所有可读取的文件和服务器数据目录中的文件。然后可以使用SELECT
访问该表,将其内容传输到客户端主机。GRANT OPTION
允许用户将他们的权限授予其他用户。拥有不同权限并且具有GRANT OPTION
权限的两个用户可以组合权限。ALTER
可能被用于通过重命名表来破坏权限系统。SHUTDOWN
可以被滥用来通过终止服务器来完全拒绝其他用户的服务。PROCESS
可以用于查看当前执行语句的纯文本,包括设置或更改密码的语句。SUPER
可以用于终止其他会话或更改服务器操作方式。- 为
mysql
系统数据库本身授予的权限可以用于更改密码和其他访问权限信息:
- 密码被加密存储,因此恶意用户不能简单地读取它们以了解明文密码。但是,具有对
mysql.user
系统表authentication_string
列的写入访问权限的用户可以更改账户的密码,然后使用该账户连接到 MySQL 服务器。 - 为
mysql
系统数据库授予的INSERT
或UPDATE
权限使用户能够添加权限或修改现有权限。 - 为
mysql
系统数据库的DROP
允许用户删除权限表,甚至是数据库本身。
静态权限与动态权限
MySQL 支持静态和动态权限:
- 静态权限内置于服务器中。它们始终可供授予给用户帐户,并且无法注销。
- 动态权限可以在运行时注册和注销。这会影响它们的可用性:未注册的动态权限无法授予。
例如,SELECT
和 INSERT
权限是静态的,并且始终可用,而实现它的组件已启用时才会提供动态权限。
本节的其余部分描述了 MySQL 中动态权限的工作原理。讨论中使用术语“组件”,但同样适用于插件。
注意
服务器管理员应该了解哪些服务器组件定义了动态权限。对于 MySQL 发行版,定义动态权限的组件的文档描述了这些权限。
第三方组件也可能定义动态权限;管理员应该了解这些权限,并且不安装可能会与服务器操作发生冲突或危害的组件。例如,如果两个组件都定义了相同名称的权限,则一个组件会与另一个组件发生冲突。组件开发人员可以通过选择以组件名称为前缀的权限名称来减少此类情况发生的可能性。
服务器在内存中维护已注册的动态权限集。在服务器关闭时进行注销。
通常,定义动态权限的组件在安装时会注册它们,在初始化序列期间。当卸载时,组件不会注销其已注册的动态权限。(这是当前的做法,而不是要求。也就是说,组件可以,但不会在任何时候注销其注册的权限。)
尝试注册已经注册的动态权限不会出现警告或错误。考虑以下语句序列:
INSTALL COMPONENT 'my_component'; UNINSTALL COMPONENT 'my_component'; INSTALL COMPONENT 'my_component';
第一个 INSTALL COMPONENT
语句注册了组件 my_component
定义的任何权限,但 UNINSTALL COMPONENT
不会注销它们。对于第二个 INSTALL COMPONENT
语句,它注册的组件权限已经被发现已经注册,但不会出现警告或错误。
动态权限仅适用于全局级别。服务器在mysql.global_grants
系统表中存储有关动态权限对用户帐户的当前分配的信息:
- 服务器在启动时自动注册
global_grants
中命名的权限(除非提供了--skip-grant-tables
选项)。 GRANT
和REVOKE
语句修改global_grants
的内容。- 在
global_grants
中列出的动态权限分配是持久的。它们在服务器关闭时不会被移除。
示例:以下语句授予用户u1
在副本上控制复制(包括组复制)和修改系统变量所需的权限:
GRANT REPLICATION_SLAVE_ADMIN, GROUP_REPLICATION_ADMIN, BINLOG_ADMIN ON *.* TO 'u1'@'localhost';
授予的动态权限将出现在SHOW GRANTS
语句和INFORMATION_SCHEMA
USER_PRIVILEGES
表的输出中。
对于GRANT
和REVOKE
在全局级别,任何未被识别为静态的命名权限将与当前注册的动态权限集合进行检查,如果找到则授予。否则,将发生错误以指示未知的权限标识符。
对于GRANT
和REVOKE
在全局级别,ALL [PRIVILEGES]
的含义包括所有静态全局权限,以及当前注册的所有动态权限:
GRANT ALL
在全局级别授予所有静态全局权限和当前注册的所有动态权限。在执行GRANT
语句后注册的动态权限不会追溯地授予任何帐户。REVOKE ALL
在全局级别撤销所有授予的静态全局权限和所有授予的动态权限。
FLUSH PRIVILEGES
语句读取global_grants
表中的动态权限分配,并注册在那里找到的任何未注册的权限。
有关 MySQL Server 和 MySQL 发行版中包含的组件提供的动态权限的描述,请参见 Section 8.2.2, “MySQL 提供的权限”。
从 SUPER 迁移帐户到动态权限
在 MySQL 8.0 中,许多以前需要SUPER
权限的操作也与更有限范围的动态权限相关联。(有关这些权限的描述,请参见第 8.2.2 节,“MySQL 提供的权限”。)每个这样的操作可以通过授予相关的动态权限而不是SUPER
权限来允许给账户。这种变化通过使 DBA 避免授予SUPER
权限并更紧密地调整用户权限以符合允许的操作来提高安全性。SUPER
现已被弃用;预计它将在 MySQL 的未来版本中被移除。
当移除SUPER
权限时,以前需要SUPER
权限的操作将失败,除非被授予SUPER
权限的账户迁移到适当的动态权限。使用以下说明来实现这一目标,以便在SUPER
权限被移除之前账户已准备就绪:
- 执行此查询以识别被授予
SUPER
权限的账户:
SELECT GRANTEE FROM INFORMATION_SCHEMA.USER_PRIVILEGES WHERE PRIVILEGE_TYPE = 'SUPER';
- 对于由上述查询确定的每个账户,确定其需要
SUPER
权限的操作。然后授予相应操作的动态权限,并撤销SUPER
。
例如,如果'u1'@'localhost'
需要SUPER
权限用于二进制日志清除和系统变量修改,以下语句将对账户进行所需更改:
GRANT BINLOG_ADMIN, SYSTEM_VARIABLES_ADMIN ON *.* TO 'u1'@'localhost'; REVOKE SUPER ON *.* FROM 'u1'@'localhost';
- 在修改了所有适用账户之后,第一步中的
INFORMATION_SCHEMA
查询应产生一个空结果集。
8.2.3 授权表
mysql
系统数据库包含几个授权表,其中包含有关用户账户和其持有的权限的信息。本节描述了这些表。有关系统数据库中其他表的信息,请参阅第 7.3 节,“mysql 系统模式”。
此处讨论了授权表的基本结构以及服务器在与客户端交互时如何使用其内容。然而,通常情况下不直接修改授权表。当您使用诸如CREATE USER
, GRANT
, 和 REVOKE
等账户管理语句设置账户和控制每个账户可用权限时,修改是间接发生的。请参阅第 15.7.1 节,“账户管理语句”。当您使用这些语句执行账户操作时,服务器会代表您修改授权表。
注意
不鼓励直接使用诸如INSERT
, UPDATE
, 或 DELETE
等语句直接修改授权表,这样做风险自负。服务器可以忽略由于这些修改导致的格式错误的行。
对于任何修改授权表的操作,服务器会检查表是否具有预期的结构,如果不是,则会产生错误。要将表更新为预期的结构,请执行 MySQL 升级过程。请参阅第三章,“升级 MySQL”。
- 授权表概述
- 用户和数据库授权表
- tables_priv 和 columns_priv 授权表
- procs_priv 授权表
- proxies_priv 授权表
- 全局授权表
- 默认角色授权表
- 角色边缘授权表
- 密码历史授权表
- 授予表范围列属性
- 授予表权限列属性
- 授予表并发性
授予表概述
这些mysql
数据库表包含授予信息:
user
: 用户账户,静态全局权限和其他非权限列。global_grants
: 动态全局权限。db
: 数据库级权限。tables_priv
: 表级权限。columns_priv
: 列级权限。procs_priv
: 存储过程和函数权限。proxies_priv
: 代理用户权限。default_roles
: 默认用户角色。role_edges
: 角色子图的边缘。password_history
: 密码更改历史。
有关静态和动态全局权限之间的区别,请参阅静态与动态权限。
在 MySQL 8.0 中,授予表使用InnoDB
存储引擎并且是事务性的。在 MySQL 8.0 之前,授予表使用MyISAM
存储引擎并且是非事务性的。授予表存储引擎的更改使得伴随的账户管理语句的行为也发生了变化,例如CREATE USER
或GRANT
。以前,命名多个用户的账户管理语句可能对某些用户成功,对其他用户失败。现在,每个语句都是事务性的,要么对所有命名用户成功,要么回滚并且如果出现任何错误则不起作用。
每个授予表包含范围列和权限列:
- 范围列确定表中每行的范围;也就是说,行适用的上下文。例如,具有
Host
和User
值为'h1.example.net'
和'bob'
的user
表行适用于由指定用户名称为bob
的客户端从主机h1.example.net
进行的身份验证连接。类似地,具有Host
,User
和Db
列值为'h1.example.net'
,'bob'
和'reports'
的db
表行适用于bob
从主机h1.example.net
连接以访问reports
数据库。tables_priv
和columns_priv
表包含指示每行适用于哪些表或表/列组合的范围列。procs_priv
范围列指示每行适用于的存储过程。 - 特权列指示表行授予哪些特权;也就是说,它允许执行哪些操作。服务器将各种授权表中的信息组合起来,形成用户特权的完整描述。第 8.2.7 节,“访问控制,第 2 阶段:请求验证”描述了这方面的规则。
此外,授权表可能包含用于除范围或特权评估之外的其他目的的列。
服务器使用授权表的方式如下:
user
表的范围列确定是否拒绝或允许传入连接。对于允许的连接,在user
表中授予的任何特权表示用户的静态全局特权。在此表中授予的任何特权都适用于所有服务器上的数据库。
注意
因为任何静态全局特权都被视为所有数据库的特权,任何静态全局特权都使用户能够通过SHOW DATABASES
或通过检查INFORMATION_SCHEMA
的SCHEMATA
表来查看所有数据库名称,除了在数据库级别通过部分撤销限制的数据库。global_grants
表列出了对用户帐户分配的动态全局特权。对于每行,范围列确定具有特权列中命名的特权的用户。db
表的范围列确定哪些用户可以从哪些主机访问哪些数据库。特权列确定允许的操作。在数据库级别授予的特权适用于数据库及其所有对象,如表和存储程序。tables_priv
和columns_priv
表类似于db
表,但更加精细:它们适用于表和列级别,而不是数据库级别。在表级别授予的特权适用于表及其所有列。在列级别授予的特权仅适用于特定列。procs_priv
表适用于存储例程(存储过程和函数)。在例程级别授予的权限仅适用于单个过程或函数。proxies_priv
表指示哪些用户可以代表其他用户行事,以及用户是否可以向其他用户授予PROXY
权限。default_roles
和role_edges
表包含有关角色关系的信息。password_history
表保留先前选择的密码,以启用对密码重用的限制。请参阅 第 8.2.15 节,“密码管理”。
服务器在启动时将授予表的内容读入内存。您可以通过发出 FLUSH PRIVILEGES
语句或执行 mysqladmin flush-privileges 或 mysqladmin reload 命令来告诉它重新加载表。对授权表的更改将按照 第 8.2.13 节,“权限更改生效时间” 中指示的方式生效。
当您修改帐户时,最好验证您的更改是否产生预期效果。要检查给定帐户的权限,请使用 SHOW GRANTS
语句。例如,要确定授予具有用户名和主机名值为 bob
和 pc84.example.com
的帐户的权限,请使用此语句:
SHOW GRANTS FOR 'bob'@'pc84.example.com';
要显示帐户的非权限属性,请使用 SHOW CREATE USER
:
SHOW CREATE USER 'bob'@'pc84.example.com';
用户和数据库授权表
服务器在访问控制的第一和第二阶段都使用 mysql
数据库中的 user
和 db
表(参见 第 8.2 节,“访问控制和账户管理”)。这里显示了 user
和 db
表中的列。
表 8.4 user 和 db 表列
表名 | user |
db |
范围列 | Host |
Host |
User |
Db |
|
User |
||
权限列 | Select_priv |
Select_priv |
Insert_priv |
Insert_priv |
|
Update_priv |
Update_priv |
|
Delete_priv |
Delete_priv |
|
Index_priv |
Index_priv |
|
Alter_priv |
Alter_priv |
|
Create_priv |
Create_priv |
|
Drop_priv |
Drop_priv |
|
Grant_priv |
Grant_priv |
|
Create_view_priv |
Create_view_priv |
|
Show_view_priv |
Show_view_priv |
|
Create_routine_priv |
Create_routine_priv |
|
Alter_routine_priv |
Alter_routine_priv |
|
Execute_priv |
Execute_priv |
|
Trigger_priv |
Trigger_priv |
|
Event_priv |
Event_priv |
|
Create_tmp_table_priv |
Create_tmp_table_priv |
|
Lock_tables_priv |
Lock_tables_priv |
|
References_priv |
References_priv |
|
Reload_priv |
||
Shutdown_priv |
||
Process_priv |
||
File_priv |
||
Show_db_priv |
||
Super_priv |
||
Repl_slave_priv |
||
Repl_client_priv |
||
Create_user_priv |
||
Create_tablespace_priv |
||
Create_role_priv |
||
Drop_role_priv |
||
安全列 | ssl_type |
|
ssl_cipher |
||
x509_issuer |
||
x509_subject |
||
plugin |
||
authentication_string |
||
password_expired |
||
password_last_changed |
||
password_lifetime |
||
account_locked |
||
Password_reuse_history |
||
Password_reuse_time |
||
Password_require_current |
||
User_attributes |
||
资源控制列 | max_questions |
|
max_updates |
||
max_connections |
||
max_user_connections |
||
表名 | user |
db |
user
表的plugin
和authentication_string
列存储身份验证插件和凭据信息。
服务器使用帐户行的plugin
列中命名的插件来验证帐户的连接尝试。
plugin
列必须非空。在启动时,以及在执行FLUSH PRIVILEGES
时,服务器会检查user
表行。对于任何plugin
列为空的行,服务器会向错误日志写入以下警告:
[Warning] User entry '*user_name*'@'*host_name*' has an empty plugin value. The user will be ignored and no one can login with this user anymore.
要为缺少插件的帐户分配插件,请使用ALTER USER
语句。
password_expired
列允许 DBA 过期帐户密码并要求用户重置密码。默认的password_expired
值为'N'
,但可以使用ALTER USER
语句设置为'Y'
。帐户密码过期后,在后续连接到服务器时,帐户执行的所有操作都会导致错误,直到用户发出ALTER USER
语句以建立新的帐户密码。
注意
尽管可以通过将过期密码设置为当前值来“重置”过期密码,但最好根据良好的政策选择不同的密码。DBA 可以通过建立适当的密码重用策略来强制不重用。请参阅密码重用策略。
password_last_changed
是一个TIMESTAMP
列,指示密码上次更改的时间。该值仅对使用 MySQL 内置身份验证插件(mysql_native_password
、sha256_password
或caching_sha2_password
)的帐户为非NULL
。对于其他帐户,如使用外部身份验证系统进行身份验证的帐户,该值为NULL
。
password_last_changed
由 CREATE USER
、ALTER USER
和 SET PASSWORD
语句以及创建帐户或更改帐户密码的 GRANT
语句更新。
password_lifetime
指示帐户密码的生命周期,以天为单位。如果密码已超过其生命周期(使用 password_last_changed
列进行评估),当客户端使用该帐户连接时,服务器将视密码为已过期。大于零的 N
值表示密码必须每 N
天更改一次。值为 0 禁用自动密码过期。如果值为 NULL
(默认值),则全局过期策略适用,由 default_password_lifetime
系统变量定义。
account_locked
指示帐户是否被锁定(参见第 8.2.20 节,“帐户锁定”)。
Password_reuse_history
是帐户的 PASSWORD HISTORY
选项的值,或者对于默认历史记录为 NULL
。
Password_reuse_time
是帐户的 PASSWORD REUSE INTERVAL
选项的值,或者对于默认间隔为 NULL
。
Password_require_current
(MySQL 8.0.13 中新增)对应于帐户的 PASSWORD REQUIRE
选项的值,如下表所示。
表 8.5 允许的 Password_require_current 值
Password_require_current 值 | 对应的 PASSWORD REQUIRE 选项 |
'Y' |
PASSWORD REQUIRE CURRENT |
'N' |
PASSWORD REQUIRE CURRENT OPTIONAL |
NULL |
PASSWORD REQUIRE CURRENT DEFAULT |
User_attributes
(MySQL 8.0.14 中新增)是一个以 JSON 格式存储帐户属性的列,这些属性未存储在其他列中。截至 MySQL 8.0.21,INFORMATION_SCHEMA
通过 USER_ATTRIBUTES
表公开这些属性。
User_attributes
列可能包含这些属性:
additional_password
:次要密码,如果有的话。请参阅双密码支持。Restrictions
:限制列表,如果有的话。限制是通过部分撤销操作添加的。属性值是一个元素数组,每个元素都有Database
和Restrictions
键,指示受限数据库的名称和适用于其上的限制(参见第 8.2.12 节,“使用部分撤销进行权限限制”)。Password_locking
: 如果有的话,是关于失败登录跟踪和临时账户锁定的条件(参见失败登录跟踪和临时账户锁定)。Password_locking
属性根据CREATE USER
和ALTER USER
语句的FAILED_LOGIN_ATTEMPTS
和PASSWORD_LOCK_TIME
选项进行更新。该属性值是一个哈希,其中包含failed_login_attempts
和password_lock_time_days
键,指示为该账户指定的选项值。如果某个键缺失,则其值隐式为 0。如果键值隐式或显式为 0,则相应的功能被禁用。此属性在 MySQL 8.0.19 中添加。multi_factor_authentication
:mysql.user
系统表中的行具有一个plugin
列,指示认证插件。对于单因素认证,该插件是唯一的认证因素。对于多因素认证的两因素或三因素形式,该插件对应于第一个认证因素,但必须为第二和第三因素存储额外信息。multi_factor_authentication
属性保存了这些信息。此属性在 MySQL 8.0.27 中添加。multi_factor_authentication
值是一个数组,其中每个数组元素都是一个哈希,描述了使用以下属性描述的认证因素:
plugin
: 认证插件的名称。authentication_string
: 认证字符串的值。passwordless
: 一个标志,表示用户是否可以在没有密码的情况下使用(仅使用安全令牌作为唯一的认证方法)。requires_registration
: 一个定义用户账户是否已注册安全令牌的标志。
- 第一个和第二个数组元素描述了多因素认证因素 2 和 3。
如果没有属性适用,则User_attributes
为NULL
。
例子:一个具有次要密码和部分撤销数据库权限的账户在列值中具有additional_password
和Restrictions
属性:
mysql> SELECT User_attributes FROM mysql.User WHERE User = 'u'\G *************************** 1\. row *************************** User_attributes: {"Restrictions": [{"Database": "mysql", "Privileges": ["SELECT"]}], "additional_password": "*hashed_credentials*"}
要确定存在哪些属性,请使用JSON_KEYS()
函数:
SELECT User, Host, JSON_KEYS(User_attributes) FROM mysql.user WHERE User_attributes IS NOT NULL;
要提取特定属性,例如Restrictions
,请执行以下操作:
SELECT User, Host, User_attributes->>'$.Restrictions' FROM mysql.user WHERE User_attributes->>'$.Restrictions' <> '';
这是存储在multi_factor_authentication
中的信息示例:
{ "multi_factor_authentication": [ { "plugin": "authentication_ldap_simple", "passwordless": 0, "authentication_string": "ldap auth string", "requires_registration": 0 }, { "plugin": "authentication_fido", "passwordless": 0, "authentication_string": "", "requires_registration": 1 } ] }
tables_priv 和 columns_priv 授权表
在访问控制的第二阶段,服务器执行请求验证,以确保每个客户端对其发出的每个请求都具有足够的权限。除了user
和db
授权表外,服务器还可能在涉及表的请求中查阅tables_priv
和columns_priv
表。后者在表和列级别提供更精细的权限控制。它们具有以下表中显示的列。
表 8.6 tables_priv 和 columns_priv 表列
表名 | tables_priv |
columns_priv |
范围列 | 主机 |
主机 |
数据库 |
数据库 |
|
用户 |
用户 |
|
表名 |
表名 |
|
列名 |
||
权限列 | 表权限 |
列权限 |
列权限 |
||
其他列 | 时间戳 |
时间戳 |
授权者 |
时间戳
和 授权者
列分别设置为当前时间戳和CURRENT_USER
值,但其他情况下未使用。
procs_priv 授权表
为了验证涉及存储例程的请求,服务器可能会查阅procs_priv
表,该表具有以下表中显示的列。
表 8.7 procs_priv 表列
表名 | procs_priv |
范围列 | 主机 |
数据库 |
|
用户 |
|
例程名 |
|
例程类型 |
|
权限列 | Proc 权限 |
其他列 | 时间戳 |
授权者 |
例程类型
列是一个具有值 'FUNCTION'
或 'PROCEDURE'
的ENUM
列,用于指示行所指的例程类型。该列使得可以分别为具有相同名称的函数和过程授予权限。
时间戳
和 授权者
列未使用。
proxies_priv 授权表
proxies_priv
表记录有关代理账户的信息。它具有以下列:
主机
,用户
:代理账户;即具有被代理账户的PROXY
权限的账户。被代理主机
,被代理用户
:被代理账户。授权者
,时间戳
:未使用。With_grant
:代理账户是否可以将PROXY
权限授予其他账户。
要使账户能够向其他账户授予PROXY
特权,必须在proxies_priv
表中具有一行,其中With_grant
设置为 1,Proxied_host
和Proxied_user
设置为指示可以授予特权的账户或账户。例如,在 MySQL 安装期间创建的'root'@'localhost'
账户在proxies_priv
表中有一行,该行允许为''@''
,即所有用户和所有主机,授予PROXY
特权。这使得root
能够设置代理用户,以及委派给其他账户权限设置代理用户的权限。参见 Section 8.2.19, “Proxy Users”。
全局授权授权表
global_grants
表列出了动态全局特权当前分配给用户账户的情况。该表包含以下列:
用户
,主机
:被授予权限的账户的用户名和主机名。权限
:权限名称。WITH_GRANT_OPTION
:账户是��可以向其他账户授予特权。
默认角色授权表
default_roles
表列出了默认用户角色。它包含以下列:
主机
,用户
:应用默认角色的账户或角色。DEFAULT_ROLE_HOST
,DEFAULT_ROLE_USER
:默认角色。
角色边缘授权表
role_edges
表列出了角色子图的边缘。它包含以下列:
FROM_HOST
,FROM_USER
:被授予角色的账户。TO_HOST
,TO_USER
:授予给账户的角色。WITH_ADMIN_OPTION
:账户是否可以通过使用WITH ADMIN OPTION
向其他账户授予角色和撤销角色。
密码历史授权表
password_history
表包含有关密码更改的信息。它包含以下列:
主机
,用户
:密码更改发生的账户。密码时间戳
:密码更改发生的时间。密码
:新密码哈希值。
password_history
表累积每个账户的足够数量的非空密码,以使 MySQL 能够执行针对账户密码历史长度和重用间隔的检查。当密码更改尝试发生时,会自动修剪超出这两个限制的条目。
注意
空密码不计入密码历史记录,并可随时重新使用。
如果账户被重命名,其条目也将被重命名以匹配。如果账户被删除或其认证插件被更改,其条目将被移除。
授权表范围列属性
授权表中的范围列包含字符串。每个的默认值为空字符串。以下表显示了每个列中允许的字符数。
表 8.8 授权表范围列长度
列名 | 最大允许字符数 |
主机 ,代理主机 |
255(在 MySQL 8.0.17 之前为 60) |
用户 ,代理用户 |
32 |
数据库 |
64 |
表名 |
64 |
Column_name |
64 |
Routine_name |
64 |
Host
和 Proxied_host
的值在存储在授权表中之前会被转换为小写。
为了访问检查目的,User
、Proxied_user
、authentication_string
、Db
和 Table_name
的值的比较是区分大小写的。Host
、Proxied_host
、Column_name
和 Routine_name
的值的比较是不区分大小写的。
授权表权限列属性
user
和 db
表中列出了每个权限在一个单独的列中声明为 ENUM('N','Y') DEFAULT 'N'
。换句话说,每个权限可以被禁用或启用,默认情况下为禁用。
tables_priv
、columns_priv
和 procs_priv
表将权限列声明为 SET
列。这些列中的值可以包含由表控制的任何权限的任意组合。只有列值中列出的权限才会被启用。
表 8.9 Set-Type Privilege Column Values
表名 | 列名 | 可能的集合元素 |
tables_priv |
Table_priv |
'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter', 'Create View', 'Show view', 'Trigger' |
tables_priv |
Column_priv |
'Select', 'Insert', 'Update', 'References' |
columns_priv |
Column_priv |
'Select', 'Insert', 'Update', 'References' |
procs_priv |
Proc_priv |
'Execute', 'Alter Routine', 'Grant' |
只有 user
和 global_grants
表指定了管理权限,例如 RELOAD
、SHUTDOWN
和 SYSTEM_VARIABLES_ADMIN
。管理操作是对服务器本身的操作,不是特定于数据库的,因此没有理由在其他授权表中列出这些权限。因此,服务器只需要查看 user
和 global_grants
表来确定用户是否可以执行管理操作。
FILE
权限也仅在 user
表中指定。它不是一种管理权限,而是用户在服务器主机上读取或写入文件的能力与所访问的数据库无关。
授权表并发性
从 MySQL 8.0.22 开始,为了允许在 MySQL 授权表上进行并发的 DML 和 DDL 操作,以前在 MySQL 授权表上获取行锁的读操作将作为非锁定读取执行。在 MySQL 授权表上执行为非锁定读取的操作包括:
- 通过联接列表和子查询从授权表中读取数据的
SELECT
语句和其他只读语句,包括使用任何事务隔离级别的SELECT ... FOR SHARE
语句。 - 从授权表中读取数据的 DML 操作(通过连接列表或子查询)但不修改它们,在任何事务隔离级别下使用。
从授权表中读取数据时不再获取行锁的语句,在使用基于语句的复制时执行会报告警告。
当使用 -binlog_format=mixed
时,从授权表中读取数据的 DML 操作会被写入二进制日志作为行事件,以使操作对混合模式复制安全。
SELECT ... FOR SHARE
语句从授权表中读取数据时会报告警告。使用FOR SHARE
子句时,不支持在授权表上进行读取锁定。
从授权表中读取数据并使用SERIALIZABLE
隔离级别执行的 DML 操作会报告警告。在使用SERIALIZABLE
隔离级别时通常会获取的读取锁在授权表上不受支持。
MySQL8 中文参考(二十四)(3)https://developer.aliyun.com/article/1566156