该mysql
系统数据库包括包含关于用户帐户和他们持有的特权信息的几个授权表。本节介绍这些表。有关系统数据库中其他表的信息,请参见第5.3节“mysql系统数据库”。
通常情况下,操纵授权表的内容,加以修改间接使用账户管理语句,例如 CREATE USER
, GRANT
以及 REVOKE
设立账户并控制权限提供给每一个。见 第13.7.1节“账户管理声明”。这里的讨论描述了授权表的底层结构以及服务器在与客户端交互时如何使用它们的内容。
using语句,如授权表的直接修改 INSERT
, UPDATE
或 DELETE
不鼓励,并在您自行承担风险。服务器可以自由地忽略由于这些修改而导致格式错误的行。
从MySQL 5.7.18开始,对于修改授权表的任何操作,服务器将检查表是否具有预期的结构,如果没有,则会产生错误。必须运行mysql_upgrade才能将表更新为预期的结构。
这些mysql
数据库表包含授权信息:
每个授权表包含作用域列和特权列:
-
范围列确定表中每行的范围; 也就是行应用的上下文。例如,
user
与表行Host
和User
的值'thomas.loc.gov'
和'bob'
适用于认证到来自主机的服务器进行连接,thomas.loc.gov
由客户端指定的用户名bob
。同样,db
表一行Host
,User
和Db
列值'thomas.loc.gov'
,'bob'
而'reports'
当应用bob
从主机连接thomas.loc.gov
来访问reports
数据库。 表tables_priv
和columns_priv
表包含指示每行应用的表或表/列组合的作用域列。该procs_priv
范围列表示存储程序到各行适用。 -
特权列指示表行授予的特权; 也就是说,它允许执行哪些操作。服务器将各种授权表中的信息合并,形成用户权限的完整描述。 第6.2.5节“访问控制,阶段2:请求验证”介绍了这些规则。
服务器以下列方式使用授权表:
-
的
user
表范围列确定是否拒绝或允许传入连接。对于允许的连接,user
表中授予的任何特权 指示用户的全局权限。此表中授予的任何权限适用于 服务器上的所有数据库。警告因为任何全局权限被认为是所有数据库的特权,任何全局权限都可以让用户通过
SHOW DATABASES
或通过检查SCHEMATA
表 查看所有数据库名称INFORMATION_SCHEMA
。 -
该
db
表范围列决定哪些用户可以访问哪些数据库从哪个主机。特权列确定允许的操作。在数据库级授予的权限适用于数据库和数据库中的所有对象,例如表和存储的程序。 -
在
tables_priv
与columns_priv
表类似于db
表,但是更精致:他们在申请表和列级应用而非在数据库级。在表级授予的权限适用于表及其所有列。在列级别授予的权限仅适用于特定列。 -
该
procs_priv
表适用于存储的例程(过程和函数)。在例程级别授予的权限仅适用于单个过程或函数。 -
该
proxies_priv
表指示哪些用户可以作为其他用户的代理,以及用户是否可以PROXY
向其他用户授予权限。
服务器使用user
与 db
表中的mysql
在两个访问控制的第一和第二阶段的数据库(参见6.2节,“MySQL访问权限系统”)。中列 user
和db
表如下所示。
表6.3用户和数据库表列
表名称 | user | db |
---|---|---|
范围列 | Host | Host |
User | Db | |
Password | 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 | ||
安全栏 | ssl_type | |
ssl_cipher | ||
x509_issuer | ||
x509_subject | ||
plugin | ||
authentication_string | ||
password_expired | ||
password_last_changed | ||
password_lifetime | ||
account_locked | ||
资源控制列 | max_questions | |
max_updates | ||
max_connections | ||
max_user_connections |
该user
表plugin
, Password
和 authentication_string
列存储身份验证插件和证书信息。在MySQL 5.7.6中,Password
列已被删除,所有凭据都存储在 authentication_string
列中。
如果一个帐户行在该plugin
列中指定一个插件,则服务器使用它来验证该帐户的连接尝试。它是否使用 Password
和authentication_string
列值。
从MySQL 5.7.2起,plugin
列必须非空。
在MySQL 5.7.2之前,plugin
帐号行的列允许为空。在这种情况下,服务器认证使用的帐户 mysql_native_password
或mysql_old_password
插件含蓄,根据在密码哈希的格式 Password
列。如果 Password
值为空或4.1密码散列(41个字符),则服务器使用mysql_native_password
。如果密码值是4.1之前的密码散列(16个字符),则服务器使用 mysql_old_password
。(有关这些哈希格式的其他信息,请参见第6.1.2.4节“MySQL中的密码哈希”。)客户端必须与Password
帐户行列中的密码相匹配。
在启动时,在运行时 FLUSH PRIVILEGES
执行时,服务器检查user
表行。从MySQL 5.7.2开始,对于任何具有空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.
要解决此问题,请参见第6.5.1.3节“迁移之前的4.1密码散列和mysql_old_password插件”。
该password_expired
列允许DBA过期帐户密码,并要求用户重置其密码。默认password_expired
值为 'N'
,但可以设置为'Y'
与ALTER USER
语句。帐户密码已过期后,帐户在与服务器的后续连接中执行的所有操作都会导致错误,直到用户发出 ALTER USER
声明(对于MySQL 5.7.6及更高版本)或SET PASSWORD
语句(MySQL 5.7.6之前)才能建立一个新的帐号密码。
密码到期后可以通过将密码设置为当前值来“ 重置 ”密码。作为良好的政策,最好选择不同的密码。
password_last_changed
(添加在MySQL 5.7.4中)是一个TIMESTAMP
列,指示上次更改密码的时间。该值是非NULL
只为使用MySQL内置的身份验证方法(使用的身份验证插件帐户的帐户 mysql_native_password
, mysql_old_password
或 sha256_password
)。该值 NULL
用于其他帐户,例如使用外部身份验证系统进行身份验证的帐户。
password_last_changed
通过更新 CREATE USER
, ALTER USER
和 SET PASSWORD
报表,并通过 GRANT
创造一个帐户或更改帐户密码的语句。
password_lifetime
(添加在MySQL 5.7.4中)表示账户密码的生存期,以天为单位。如果密码超过其使用寿命(使用password_last_changed
列进行评估 ),则当客户端使用该帐户进行连接时,服务器会认为密码已过期。的值N
大于零意味着该密码必须在每次更改 N
天。值为0将禁用自动密码到期。如果值为NULL
(默认值),则全局过期策略将按default_password_lifetime
系统变量定义。
account_locked
(添加在MySQL 5.7.6中)指示帐户是否被锁定(请参见 第6.3.11节“用户帐户锁定”)。
在访问控制的第二阶段,服务器执行请求验证,以确保每个客户端对其发出的每个请求具有足够的权限。除了 授予表user
和db
授权表之外,服务器还可以查询tables_priv
和 columns_priv
表中涉及表的请求。后一表在表和列级别提供更好的权限控制。它们具有下表所示的列。
表6.4 tables_priv和columns_priv表列
表名称 | tables_priv | columns_priv |
---|---|---|
范围列 | Host | Host |
Db | Db | |
User | User | |
Table_name | Table_name | |
Column_name | ||
特权列 | Table_priv | Column_priv |
Column_priv | ||
其他列 | Timestamp | Timestamp |
Grantor |
的Timestamp
和Grantor
列被设置为当前时间戳和 CURRENT_USER
值,分别,但其他未使用的。
为了验证涉及存储例程的请求,服务器可以查询procs_priv
具有下表所示列的表。
表6.5 procs_priv表列
表名称 | procs_priv |
---|---|
范围列 | Host |
Db | |
User | |
Routine_name | |
Routine_type | |
特权列 | Proc_priv |
其他列 | Timestamp |
Grantor |
该Routine_type
列是一个 ENUM
列,其值为 'FUNCTION'
或'PROCEDURE'
指示行引用的例程类型。此列可以为功能和具有相同名称的过程单独授予权限。
在Timestamp
与Grantor
列未使用。
该proxies_priv
表记录有关代理帐户的信息。它有这些列:
要使帐户能够授予PROXY
其他帐户的 权限,它必须在proxies_priv
表中具有一行,With_grant
设置为1, Proxied_host
并Proxied_user
设置为指示可授予权限的帐户或帐户。例如,'root'@'localhost'
在MySQL安装期间创建的 帐户在proxies_priv
表中有一行可以授予所有用户和所有主机的 PROXY
权限 ''@''
。这使得root
能够设置代理用户,以及委托其他帐户设置代理用户的权限。请参阅第6.3.10节“代理用户”。
授权表中的范围列包含字符串。每个的默认值是空字符串。下表显示每列中允许的字符数。
表6.6授予表范围列长度
列名称 | 最大允许字符 |
---|---|
Host , Proxied_host | 60 |
User , Proxied_user | 32(16之前MySQL 5.7.8) |
Password | 41 |
Db | 64 |
Table_name | 64 |
Column_name | 64 |
Routine_name | 64 |
对于访问检查目的,进行比较 User
,Proxied_user
, Password
, authentication_string
,Db
,和Table_name
的值是大小写敏感的。的比较Host
, Proxied_host
,Column_name
,和Routine_name
的值是不区分大小写。
在user
和db
表列出了被声明为一个单独的列每个特权 ENUM('N','Y') DEFAULT 'N'
。换句话说,可以禁用或启用每个权限,默认为禁用。
the tables_priv
, columns_priv
and procs_priv
表将权限列声明为 SET
列。这些列中的值可以包含由表控制的特权的任意组合。只有列值中列出的那些权限才被启用。
表6.7 Set-Type特权列值
表名称 | 列名称 | 可能的设置元素 |
---|---|---|
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
表指定了管理权限,例如RELOAD
和 SHUTDOWN
。管理操作是服务器本身的操作,而不是数据库特定的,因此没有理由在其他授权表中列出这些权限。因此,服务器只需要查询 user
表来确定用户是否可以执行管理操作。
该FILE
权限也仅在指定的user
表。它不是这样的管理权限,但用户在服务器主机上读取或写入文件的能力与所访问的数据库无关。
服务器在启动时将授权表的内容读入内存。您可以通过发出FLUSH PRIVILEGES
语句或执行mysqladmin flush-privileges或mysqladmin reload 命令来告诉它重新加载表 。授权表的更改将在第6.2.6节“权限更改生效时”中指示 。
当您修改帐户时,最好验证您的更改是否具有预期的效果。要检查给定帐户的权限,请使用该SHOW GRANTS
语句。例如,要确定与用户名和主机名值授予一个帐户的权限 bob
和pc84.example.com
使用下面的语句:
SHOW GRANTS FOR 'bob'@'pc84.example.com';
要显示帐户的非特权属性,请使用 SHOW CREATE USER
:
SHOW CREATE USER 'bob'@'pc84.example.com';