当您尝试连接到 MySQL 服务器时,服务器会根据以下条件接受或拒绝连接:
您的身份以及您是否可以通过提供适当的凭据来验证它。
您的帐户是被锁定还是解锁。
服务器首先检查凭据,然后检查帐户锁定状态。任一步骤的失败都会导致服务器完全拒绝您的访问。否则,服务器接受连接,然后进入阶段 2 等待请求。
服务器使用表中的列执行身份和凭据检查user,仅当满足以下条件时才接受连接:
客户端主机名和用户名与 某些表行中的
Host和User列相匹配。有关管理允许和 值user的规则,请参阅第 6.2.4 节,“指定帐户名称”。HostUser客户端提供行中指定的凭据(例如,密码),如
authentication_string列所示。使用列中命名的身份验证插件解释凭据plugin。该行表示该帐户已解锁。锁定状态记录在
account_locked列中,该列的值必须为'N'。可以使用CREATE USERorALTER USER语句设置或更改帐户锁定。
您的身份基于两条信息:
您的 MySQL 用户名。
您连接的客户端主机。
如果User列值不为空,则传入连接中的用户名必须完全匹配。如果该
User值为空,则匹配任何用户名。如果user与传入连接匹配的表行具有空白用户名,则该用户被认为是没有名称的匿名用户,而不是具有客户端实际指定名称的用户。这意味着在连接期间(即第 2 阶段),所有进一步的访问检查都将使用空白用户名。
The authentication_string column can be blank.
This is not a wildcard and does not mean that any password
matches. 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. In this case, it
is possible that an external password is also used to authenticate
to the MySQL server.
Nonblank password values stored in the
authentication_string column of the
user table are encrypted. 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). 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”.
From MySQL's point of view, the encrypted password is the
real password, so you should never give
anyone access to it. In particular, do not give
nonadministrative users read access to tables in the
mysql system database.
The following table shows how various combinations of
User and Host values in the
user table apply to incoming connections.
User Value |
Host Value |
Permissible Connections |
|---|---|---|
'fred' |
'h1.example.net' |
fred, connecting from
h1.example.net |
'' |
'h1.example.net' |
Any user, connecting from h1.example.net |
'fred' |
'%' |
fred, connecting from any host |
'' |
'%' |
Any user, connecting from any host |
'fred' |
'%.example.net' |
fred, connecting from any host in the
example.net domain |
'fred' |
'x.example.%' |
fred, connecting from
x.example.net,
x.example.com,
x.example.edu, and so on; this is
probably not useful |
'fred' |
'198.51.100.177' |
fred, connecting from the host with IP address
198.51.100.177 |
'fred' |
'198.51.100.%' |
fred, connecting from any host in the
198.51.100 class C subnet |
'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. The preceding set of examples
demonstrates this: Several of the entries shown match a connection
from h1.example.net by fred.
When multiple matches are possible, the server must determine which of them to use. It resolves this issue as follows:
Whenever the server reads the
usertable into memory, it sorts the rows.When a client attempts to connect, the server looks through the rows in sorted order.
The server uses the first row that matches the client host name and user name.
The server uses sorting rules that order rows with the
most-specific Host values first:
Literal IP addresses and host names are the most specific.
The specificity of a literal IP address is not affected by whether it has a netmask, so
198.51.100.13and198.51.100.0/255.255.255.0are considered equally specific.The pattern
'%'means “any host” and is least specific.The empty string
''also means “any host” but sorts after'%'.
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%, %).
Rows with the same Host value are ordered with
the most-specific User values first. 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.
For rows with equally-specific Host and
User values, the order is nondeterministic.
To see how this works, suppose that the user
table looks like this:
+-----------+----------+-
| 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'. The 'localhost'
row appears first in sorted order, so that is the one the server
uses.
Here is another example. Suppose that the user
table looks like this:
+----------------+----------+-
| 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.
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. As a result, jeffrey is
authenticated as an anonymous user, even though he specified a
user name when connecting.
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. (See
Section 12.16, “Information Functions”.) It returns a value in
format that indicates the user_name@host_nameUser and
Host values from the matching
user table row. Suppose that
jeffrey connects and issues the following
query:
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表并手动对其进行排序,以查看第一个匹配的位置。