当您尝试连接到 MySQL 服务器时,服务器会根据以下条件接受或拒绝连接:When you attempt to connect to a MySQL server, the server accepts or rejects the connection based on these conditions:
您的身份,以及您是否可以通过提供适当的凭据来验证身份。Your identity and whether you can verify it by supplying the proper credentials.
您的账户是被锁定还是未锁定。Whether your account is locked or unlocked.
服务器先检查凭据,然后检查账户锁定状态。在任一步骤失败时,服务器会完全拒绝您的访问。否则,服务器会接受连接,然后进入第二阶段并等待请求。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.
服务器使用 user 表中的列执行身份和凭证检查,仅在满足以下条件时才接受连接:The server performs identity and credentials checking using
columns in the user table, accepting the
connection only if these conditions are satisfied:
客户端主机名和用户名与某行
user表中的Host和User列匹配。有关允许的Host和User值的规则,请参阅 第 8.2.4 节,“指定账户名”。The client host name and user name match theHostandUsercolumns in someusertable row. For the rules governing permissibleHostandUservalues, see Section 8.2.4, “Specifying Account Names”.客户端提供该行中指定的凭证(例如密码),如
authentication_string列所示。凭证使用plugin列中所命名的身份验证插件进行解释。The client supplies the credentials specified in the row (for example, a password), as indicated by theauthentication_stringcolumn. Credentials are interpreted using the authentication plugin named in theplugincolumn.该行表示账户已解锁。锁定状态记录在
account_locked列中,该列的值必须为'N'。账户锁定可以通过CREATE USER或ALTER USER语句设置或更改。The row indicates that the account is unlocked. Locking state is recorded in theaccount_lockedcolumn, which must have a value of'N'. Account locking can be set or changed with theCREATE USERorALTER USERstatement.
您的身份基于两条信息:Your identity is based on two pieces of information:
您的 MySQL 用户名。Your MySQL user name.
您连接的客户端主机。The client host from which you connect.
如果 User 列的值非空,则传入连接中的用户名必须完全匹配。如果 User 值为空,则匹配任何用户名。如果与传入连接匹配的 user 表行的用户名为空,则该用户被视为没有名称的匿名用户,而不是客户端实际指定名称的用户。这意味着在连接持续期间(即在阶段 2 中),空用户名将用于所有进一步的访问检查。If the User column value is nonblank, the user
name in an incoming connection must match exactly. If the
User value is blank, it matches any user name.
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. 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).
authentication_string 列可以为空。这不是通配符,也不意味着任何密码都可以匹配。它意味着用户必须在不指定密码的情况下连接。用于验证客户端的插件所实现的认证方法可能使用也可能不使用 authentication_string 列中的密码。在这种情况下,也可能使用外部密码来对 MySQL 服务器进行认证。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.
存储在user表的authentication_string列中的非空密码值是加密的。MySQL 不会以明文形式存储密码以供任何人查看。而是,尝试连接的用户提供的密码会被加密(使用账户认证插件实现的密码哈希方法)。然后在连接过程中使用加密后的密码来检查密码是否正确。在此过程中,加密密码不会通过连接传输。请参见第 8.2.1 节,“账户用户名和密码”。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 8.2.1, “Account User Names and Passwords”.
从 MySQL 服务器的角度来看,加密密码就是真实密码,因此你绝不应该让任何人访问它。特别是,不要给非管理员用户读取 mysql 系统数据库中表的权限。From the MySQL server'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.
下表显示了 user 表中各种 User 和 Host 值组合如何应用于传入连接。The following table shows how various combinations of
User and Host values in the
user table apply to incoming connections.
User 值User Value |
Host 值Host Value |
允许的连接Permissible Connections |
|---|---|---|
'fred' |
'h1.example.net' |
fred,从 h1.example.net 连接fred, connecting from
h1.example.net |
'' |
'h1.example.net' |
任何用户,从 h1.example.net 连接Any user, connecting from h1.example.net |
'fred' |
'%' |
fred,从任何主机连接fred, connecting from any host |
'' |
'%' |
任何用户,从任何主机连接Any user, connecting from any host |
'fred' |
'%.example.net' |
fred,从 example.net 域中的任何主机连接fred, connecting from any host in the
example.net domain |
'fred' |
'x.example.%' |
fred,从 x.example.net、x.example.com、x.example.edu 等主机连接;这可能没有用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,从 IP 地址为 198.51.100.177 的主机连接fred, connecting from the host with IP address
198.51.100.177 |
'fred' |
'198.51.100.%' |
fred,从 198.51.100 C 类子网中的任何主机连接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 |
传入连接的客户端主机名和用户名可能与 user 表中的多行匹配。前面的一组示例演示了这一点:所示的一些条目与来自 h1.example.net 的 fred 的连接匹配。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:
每当服务器将
user表读取到内存中时,它会对行进行排序。Whenever the server reads theusertable 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.
服务器使用排序规则,将最具体的 Host 值的行排在最前:The server uses sorting rules that order rows with the
most-specific Host values first:
字面 IP 地址和主机名是最具体的。Literal IP addresses and host names are the most specific.
主机部分中带有 IP 地址的账户具有以下特定顺序:Accounts with an IP address in the host part have this order of specificity:
主机部分指定为 IP 地址的账户:Accounts that have the host part given as an IP address:
CREATE USER '
user_name'@'127.0.0.1'; CREATE USER 'user_name'@'198.51.100.44';主机部分使用 CIDR 表示法指定为 IP 地址的账户:Accounts that have the host part given as an IP address using CIDR notation:
CREATE USER '
user_name'@'192.0.2.21/8'; CREATE USER 'user_name'@'198.51.100.44/16';主机部分带有子网掩码指定为 IP 地址的账户:Accounts that have the host part given as an IP address with a subnet mask:
CREATE USER '
user_name'@'192.0.2.0/255.255.255.0'; CREATE USER 'user_name'@'198.51.0.0/255.255.0.0';
模式
'%'表示 “任意主机”,这是最不具体的。The pattern'%'means “any host” and is least specific.空字符串
''也表示 “任意主机”,但排序在'%'之后。The empty string''also means “any host” but sorts after'%'.
非 TCP(套接字文件、命名管道和共享内存)连接被视为本地连接,如果存在这样的账户,则匹配 localhost 的主机部分;否则匹配带通配符的主机部分以匹配 localhost(例如 local%、l%、%)。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%, %).
将 '%' 视为等同于 localhost 的做法已被弃用;您应预期此行为将在未来版本的 MySQL 中被移除。The treatment of '%' as equivalent to
localhost is deprecated; you should expect this
behavior to removed from a future version of MySQL.
具有相同 Host 值的行,按最具体的 User 值优先排序。空的 User 值表示“任何用户”,是最不具体的,因此对于具有相同 Host 值的行,非匿名用户排在匿名用户之前。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.
对于具有同等具体的 Host 和 User 值的行,排序是非确定性的。For rows with equally-specific Host and
User values, the order is nondeterministic.
为了了解这是如何工作的,假设 user 表看起来是这样的: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 | ... +-----------+----------+-
当客户端尝试连接时,服务器会浏览已排序的行,并使用找到的第一个匹配项。对于来自 localhost 的 jeffrey 连接,表中有两行匹配:一行的 Host 和 User 值分别为 'localhost' 和 '',另一行的值分别为 '%' 和 'jeffrey'。'localhost' 行在排序后出现在前面,因此服务器使用这一行。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.
这里是另一个例子。假设 user 表如下所示: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 | ... +----------------+----------+-
第一行匹配任何用户从 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 连接首先匹配的不是 User 列值为 'jeffrey' 的那一行,而是没有用户名的那一行。因此,即使 jeffrey 在连接时指定了用户名,他仍然作为匿名用户进行身份验证。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.
如果您能够连接到服务器,但您的权限与预期不符,您可能是以其他账户进行身份验证的。要找出服务器用来验证您的账户,请使用 CURRENT_USER() 函数。(参见 第 14.15 节,“信息函数”。)它返回一个 格式的值,该值表示匹配的 user_name@host_nameuser 表行中的 User 和 Host 值。假设 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. (See
Section 14.15, “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 |
+----------------+
这里显示的结果表明,匹配的 user 表行的 User 列值为空。换句话说,服务器正在将 jeffrey 视为匿名用户。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 表,并手动排序以查看第一个匹配项的位置。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.