当你试图联接一个MySQL服务器时,服务器基于你的身份和你是否能通过供应正确的口令验证身份来接受或拒绝连接。如果不是,服务器完全具结你的存取,否则,服务器接受连接,然后进入阶段2并且等待请求。
你的身份基于2个信息:
- 你从那个主机连接
- 你的MySQL用户名
身份检查使用3个user
表(Host
, User
和Password
)范围字段执行。服务器只有在一个user
表条目匹配你的主机名和用户名并且你提供了正确的口令时才接受连接。
在user
表范围字段可以如下被指定:
- 一个
Host
值可以是主机名或一个IP数字,或'localhost'
指出本地主机。 - 你可以在
Host
字段里使用通配符字符“%”和“_”。 - 一个
Host
值'%'
匹配任何主机名,一个空白Host
值等价于'%'
。注意这些值匹配能创建一个连接到你的服务器的任何主机! - 通配符字符在
User
字段中不允许,但是你能指定空白的值,它匹配任何名字。如果user
表匹配到来的连接的条目有一个空白的用户名,用户被认为是匿名用户(没有名字的用户),而非客户实际指定的名字。这意味着一个空白的用户名被用于在连接期间的进一步的存取检查(即,在阶段2期间)。 Password
字段可以是空白的。这不意味着匹配任何口令,它意味着用户必须不指定一个口令进行连接。
非空白Password
值代表加密的口令。 MySQL不以任何人可以看的纯文本格式存储口令,相反,正在试图联接的一个用户提供的口令被加密(使用PASSWORD()
函数),并且与存储了user
表中的已经加密的版本比较。如果他们匹配,口令是正确的。
下面的例子显示出各种user
表中Host
和User
条目的值的组合如何应用于到来的连接:
Host 值 |
User 值 |
被条目匹配的连接 |
'thomas.loc.gov' |
'fred' |
fred , 从thomas.loc.gov 连接 |
'thomas.loc.gov' |
'' |
任何用户, 从thomas.loc.gov 连接 |
'%' |
'fred' |
fred , 从任何主机连接 |
'%' |
'' |
任何用户, 从任何主机连接 |
'%.loc.gov' |
'fred' |
fred , 从在loc.gov 域的任何主机连接 |
'x.y.%' |
'fred' |
fred , 从x.y.net 、x.y.com ,x.y.edu 等联接。(这或许无用) |
'144.155.166.177' |
'fred' |
fred , 从有144.155.166.177 IP 地址的主机连接 |
'144.155.166.%' |
'fred' |
fred , 从144.155.166 C类子网的任何主机连接 |
既然你能在Host
字段使用IP通配符值(例如,'144.155.166.%'
匹配在一个子网上的每台主机),有可能某人可能企图探究这种能力,通过命名一台主机为144.155.166.somewhere.com
。为了阻止这样的企图,MySQL不允许匹配以数字和一个点起始的主机名,这样,如果你用一个命名为类似1.2.foo.com
的主机,它的名字决不会匹配授权表中Host
列。只有一个IP数字能匹配IP通配符值。
一个到来的连接可以被在user
表中的超过一个条目匹配。例如,一个由fred
从thomas.loc.gov
的连接匹配多个条目如上所述。如果超过一个匹配,服务器怎么选择使用哪个条目呢?服务器在启动时读入user
表后通过排序来解决这个问题,然后当一个用户试图连接时,以排序的顺序浏览条目,第一个匹配的条目被使用。
user
表排序工作如下,假定user
表看起来像这样:
+-----------+----------+- | Host | User | ... +-----------+----------+- | % | root | ... | % | jeffrey | ... | localhost | root | ... | localhost | | ... +-----------+----------+-
当服务器在表中读取时,它以最特定的Host
值为先的次序排列('%'
在Host
列里意味着“任何主机”并且是最不特定的)。有相同Host
值的条目以最特定的User
值为先的次序排列(一个空白User
值意味着“任何用户”并且是最不特定的)。最终排序的user
表看起来像这样:
+-----------+----------+- | Host | User | ... +-----------+----------+- | localhost | root | ... | localhost | | ... | % | jeffrey | ... | % | root | ... +-----------+----------+-
当一个连接被尝试时,服务器浏览排序的条目并使用找到的第一个匹配。对于由jeffrey
从localhost
的一个连接,在Host
列的'localhost'
条目首先匹配。那些有空白用户名的条目匹配连接的主机名和用户名。('%'/'jeffrey'
条目也将匹配,但是它不是在表中的第一匹配。)
这是另外一个例子。假定user
桌子看起来像这样:
+----------------+----------+- | Host | User | ... +----------------+----------+- | % | jeffrey | ... | thomas.loc.gov | | ... +----------------+----------+-
排序后的表看起来像这样:
+----------------+----------+- | Host | User | ... +----------------+----------+- | thomas.loc.gov | | ... | % | jeffrey | ... +----------------+----------+-
一个由jeffrey
从thomas.loc.gov
的连接被第一个条目匹配,而一个由jeffrey
从whitehouse.gov
的连接被第二个匹配。
普遍的误解是认为,对一个给定的用户名,当服务器试图对连接寻找匹配时,明确命名那个用户的所有条目将首先被使用。这明显不是事实。先前的例子说明了这点,在那里一个由jeffrey
从thomas.loc.gov
的连接没被包含'jeffrey'
作为User
字段值的条目匹配,但是由没有用户名的题目匹配!
如果你有服务器连接的问题,打印出user
表并且手工排序它看看第一个匹配在哪儿进行。