当您尝试连接到 MySQL 服务器时,服务器会根据以下条件接受或拒绝连接:
您的身份以及您是否可以通过提供适当的凭据来验证它。
您的帐户是被锁定还是解锁。
服务器首先检查凭据,然后检查帐户锁定状态。任一步骤的失败都会导致服务器完全拒绝您的访问。否则,服务器接受连接,然后进入阶段 2 等待请求。
服务器使用表中的列执行身份和凭据检查user
,仅当满足以下条件时才接受连接:
客户端主机名和用户名与 某些表行中的
Host
和User
列相匹配。有关管理允许和 值user
的规则,请参阅第 6.2.4 节,“指定帐户名称”。Host
User
客户端提供行中指定的凭据(例如,密码),如
authentication_string
列所示。使用列中命名的身份验证插件解释凭据plugin
。该行表示该帐户已解锁。锁定状态记录在
account_locked
列中,该列的值必须为'N'
。可以使用CREATE USER
orALTER 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
user
table 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.13
and198.51.100.0/255.255.255.0
are 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_name
User
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
表并手动对其进行排序,以查看第一个匹配的位置。