6.2.6 Access Control, Stage 1: Connection Verification访问控制,第1阶段:连接验证

When you attempt to connect to a MySQL server, the server accepts or rejects the connection based on these conditions:当您尝试连接到MySQL服务器时,服务器会根据以下条件接受或拒绝连接:

The server checks credentials first, then account locking state. 服务器首先检查凭据,然后检查帐户锁定状态。A failure at either step causes the server to deny access to you completely. 任何一步的失败都会导致服务器完全拒绝您的访问。Otherwise, the server accepts the connection, and then enters Stage 2 and waits for requests.否则,服务器接受连接,然后进入阶段2并等待请求。

The server performs identity and credentials checking using columns in the user table, accepting the connection only if these conditions are satisfied:服务器使用user表中的列执行身份和凭据检查,仅在满足以下条件时接受连接:

Your identity is based on two pieces of information:您的身份基于两条信息:

If the User column value is nonblank, the user name in an incoming connection must match exactly. 如果User列值为非空,则传入连接中的用户名必须完全匹配。If the User value is blank, it matches any user name. 如果User值为空,则它与任何用户名匹配。If the user table row that matches an incoming connection has a blank user name, the user is considered to be an anonymous user with no name, not a user with the name that the client actually specified. 如果与传入连接匹配的user表行的用户名为空,则该用户将被视为没有名称的匿名用户,而不是具有客户端实际指定名称的用户。This means that a blank user name is used for all further access checking for the duration of the connection (that is, during Stage 2).这意味着在连接期间(即第2阶段),将使用空白用户名进行所有进一步的访问检查。

The authentication_string column can be blank. This is not a wildcard and does not mean that any password matches. authentication_string列可以为空。这不是通配符,并不意味着任何密码都匹配。It means that the user must connect without specifying a password. 这意味着用户必须在不指定密码的情况下连接。The authentication method implemented by the plugin that authenticates the client may or may not use the password in the authentication_string column. 对客户端进行身份验证的插件实现的身份验证方法可能会也可能不会使用authentication_string列中的密码。In this case, it is possible that an external password is also used to authenticate to the MySQL server.在这种情况下,也可能使用外部密码对MySQL服务器进行身份验证。

Nonblank password values stored in the authentication_string column of the user table are encrypted. 存储在userauthentication_string列中的非空密码值被加密。MySQL does not store passwords as cleartext for anyone to see. Rather, the password supplied by a user who is attempting to connect is encrypted (using the password hashing method implemented by the account authentication plugin). MySQL不会将密码存储为明文供任何人查看。相反,尝试连接的用户提供的密码是加密的(使用帐户身份验证插件实现的密码哈希方法)。The encrypted password then is used during the connection process when checking whether the password is correct. This is done without the encrypted password ever traveling over the connection. See Section 6.2.1, “Account User Names and Passwords”.然后在连接过程中检查密码是否正确时使用加密密码。这是在没有加密密码通过连接的情况下完成的。请参阅第6.2.1节,“帐户用户名和密码”

From MySQL's point of view, the encrypted password is the real password, so you should never give anyone access to it. 从MySQL的角度来看,加密的密码是真实的密码,所以你永远不应该让任何人访问它。In particular, do not give nonadministrative users read access to tables in the mysql system database.特别是,不要让非管理员用户读取mysql系统数据库中的表。

The following table shows how various combinations of User and Host values in the user table apply to incoming connections.下表显示了user表中UserHost值的各种组合如何应用于传入连接。

User ValueHost ValuePermissible Connections允许的连接
'fred''h1.example.net'fred, connecting from h1.example.netfred,从'h1.example.net'连接
'''h1.example.net'Any user, connecting from h1.example.neth1.example.net连接的任何用户
'fred''%'fred, connecting from any host从任何主机连接的fred
'''%'Any user, connecting from any host任何用户,从任何主机连接
'fred''%.example.net'fred, connecting from any host in the example.net domainfred,从示例网域中的任何主机连接
'fred''x.example.%'fred, connecting from x.example.net, x.example.com, x.example.edu, and so on; this is probably not usefulfred,从x.example.netx.example.comx.example.edu等连接;这可能没什么用
'fred''198.51.100.177'fred, connecting from the host with IP address 198.51.100.177fred,从IP地址为198.51.100.177的主机连接
'fred''198.51.100.%'fred, connecting from any host in the 198.51.100 class C subnetfred,从198.51.100 C类子网中的任何主机连接
'fred''198.51.100.0/255.255.255.0'Same as previous example与前面的示例相同

It is possible for the client host name and user name of an incoming connection to match more than one row in the user table. 传入连接的客户端主机名和用户名可能与user表中的多行匹配。The preceding set of examples demonstrates this: Several of the entries shown match a connection from h1.example.net by fred.前面的一组示例演示了这一点:显示的几个条目与fredh1.example.net连接相匹配。

When multiple matches are possible, the server must determine which of them to use. It resolves this issue as follows:当可能有多个匹配时,服务器必须确定使用其中的哪一个。它解决这个问题如下:

The server uses sorting rules that order rows with the most-specific Host values first:服务器使用排序规则,首先对具有最特定Host值的行进行排序:

Non-TCP (socket file, named pipe, and shared memory) connections are treated as local connections and match a host part of localhost if there are any such accounts, or host parts with wildcards that match localhost otherwise (for example, local%, l%, %).非TCP(套接字文件、命名管道和共享内存)连接被视为本地连接,如果有任何此类帐户,则与localhost的主机部分匹配,否则与localhost匹配的带有通配符的主机部分(例如,local%l%%)。

Rows with the same Host value are ordered with the most-specific User values first. 具有相同Host值的行首先按最具体的User值排序。A blank User value means any user and is least specific, so for rows with the same Host value, nonanonymous users sort before anonymous users.空白User值表示“任何用户”,并且最不具体,因此对于具有相同Host值的行,非匿名用户会在匿名用户之前排序。

For rows with equally-specific Host and User values, the order is nondeterministic.对于具有相同特定HostUser值的行,顺序是不确定的。

To see how this works, suppose that the user table looks like this:要了解其工作原理,假设user表如下:

+-----------+----------+-
| Host      | User     | ...
+-----------+----------+-
| %         | root     | ...
| %         | jeffrey  | ...
| localhost | root     | ...
| localhost |          | ...
+-----------+----------+-

When the server reads the table into memory, it sorts the rows using the rules just described. The result after sorting looks like this:当服务器将表读入内存时,它会使用刚才描述的规则对行进行排序。排序后的结果如下:

+-----------+----------+-
| Host      | User     | ...
+-----------+----------+-
| localhost | root     | ...
| localhost |          | ...
| %         | jeffrey  | ...
| %         | root     | ...
+-----------+----------+-

When a client attempts to connect, the server looks through the sorted rows and uses the first match found. 当客户端尝试连接时,服务器会查看排序后的行,并使用找到的第一个匹配项。For a connection from localhost by jeffrey, two of the rows from the table match: the one with Host and User values of 'localhost' and '', and the one with values of '%' and 'jeffrey'. 对于jeffreylocalhost进行的连接,表中的两行匹配:一行的HostUser值为'localhost''',另一行的值为'%''jeffrey'The 'localhost' row appears first in sorted order, so that is the one the server uses.'localhost'行按排序顺序首先出现,因此这是服务器使用的行。

Here is another example. Suppose that the user table looks like this:这是另一个例子。假设user表如下:

+----------------+----------+-
| Host           | User     | ...
+----------------+----------+-
| %              | jeffrey  | ...
| h1.example.net |          | ...
+----------------+----------+-

The sorted table looks like this:排序后的表如下所示:

+----------------+----------+-
| Host           | User     | ...
+----------------+----------+-
| h1.example.net |          | ...
| %              | jeffrey  | ...
+----------------+----------+-

The first row matches a connection by any user from h1.example.net, whereas the second row matches a connection by jeffrey from any host.第一行匹配h1.example.net中任何用户的连接,而第二行匹配jeffrey从任何主机的连接。

Note注意

It is a common misconception to think that, for a given user name, all rows that explicitly name that user are used first when the server attempts to find a match for the connection. This is not true. 一种常见的误解是,对于给定的用户名,当服务器试图找到连接的匹配项时,会首先使用所有明确命名该用户的行。这不是真的。The preceding example illustrates this, where a connection from h1.example.net by jeffrey is first matched not by the row containing 'jeffrey' as the User column value, but by the row with no user name. 前面的示例说明了这一点,其中jeffreyh1.example.net创建的连接首先不是由包含'jeffrey'作为User列值的行匹配,而是由没有用户名的行匹配。As a result, jeffrey is authenticated as an anonymous user, even though he specified a user name when connecting.因此,即使jeffrey在连接时指定了用户名,他也被认证为匿名用户。

If you are able to connect to the server, but your privileges are not what you expect, you probably are being authenticated as some other account. 如果您能够连接到服务器,但您的权限不是您所期望的,则您可能正在作为其他帐户进行身份验证。To find out what account the server used to authenticate you, use the CURRENT_USER() function. 要找出服务器用于对您进行身份验证的帐户,请使用CURRENT_USER()函数。(See Section 12.16, “Information Functions”.) (参阅第12.16节,“信息函数”。)It returns a value in user_name@host_name format that indicates the User and Host values from the matching user table row. 它返回一个值user_name@host_name表示匹配user表行中的用户和主机值的格式。Suppose that jeffrey connects and issues the following query:假设jeffrey连接并发出以下查询:

mysql> SELECT CURRENT_USER();
+----------------+
| CURRENT_USER() |
+----------------+
| @localhost     |
+----------------+

The result shown here indicates that the matching user table row had a blank User column value. In other words, the server is treating jeffrey as an anonymous user.此处显示的结果表明,匹配的user表行的User列值为空。换句话说,服务器将jeffrey视为匿名用户。

Another way to diagnose authentication problems is to print out the user table and sort it by hand to see where the first match is being made.诊断身份验证问题的另一种方法是打印出user表并手动排序,以查看第一个匹配的位置。