当您尝试连接到MySQL服务器时,服务器会根据以下条件接受或拒绝连接:
您的身份以及您是否可以通过提供适当的凭证来验证它。
您的帐户是否被锁定或解锁。
服务器首先检查凭证,然后检查帐户锁定状态。任何一步的失败都会导致服务器完全拒绝对您的访问。否则,服务器接受连接,然后进入阶段2并等待请求。
对象中的列执行标识和凭据检查用户
表,仅在满足以下条件时才接受连接:
客户端主机名和用户名匹配
宿主
而且用户
一些列用户
表行。为规则治理允许宿主
而且用户
值,请参阅章节6.2.4,“指定帐户名称”.客户机提供行中指定的凭据(例如,密码),如
authentication_string
列。中命名的身份验证插件解释凭据插件
列。行表示解锁成功。锁定状态记录在
account_locked
列,该列的值必须为“N”
.属性可以设置或更改帐户锁定创建用户
或改变用户
声明。
你的身份基于两条信息:
您的MySQL用户名。
要连接的客户端主机。
如果用户
列值非空,则传入连接中的用户名必须完全匹配。如果用户
值为空,它匹配任何用户名。如果用户
表中匹配入站连接的行有空白用户名,则认为该用户是没有名称的匿名用户,而不是具有客户端实际指定名称的用户。这意味着在连接期间(即阶段2期间),所有进一步的访问检查都将使用一个空白用户名。
的authentication_string
列可以为空。这不是一个通配符,也不意味着任何密码都匹配。这意味着用户必须在不指定密码的情况下进行连接。插件实现的身份验证方法可以使用,也可以不使用authentication_string
列。在这种情况下,也可能使用外部密码对MySQL服务器进行身份验证。
存储在authentication_string
的列用户
表进行加密。MySQL不以明文的形式存储密码供任何人查看。相反,试图连接的用户提供的密码是加密的(使用由帐户身份验证插件实现的密码哈希方法)。在连接过程中检查密码是否正确时使用加密后的密码。这是在没有加密密码通过连接的情况下完成的。看到第6.2.1节“帐户用户名及密码”.
从MySQL的角度来看,加密的密码是真正的密码,所以你不应该让任何人访问它。特别是,中表的非管理用户不具有读访问权mysql
系统数据库.
下表显示了如何进行各种组合用户
而且宿主
中的值用户
表应用到传入连接。
用户 价值 |
宿主 价值 |
允许连接 |
---|---|---|
“弗雷德” |
“h1.example.net” |
弗雷德 ,从h1.example.net |
” |
“h1.example.net” |
任何用户,从h1.example.net |
“弗雷德” |
“%” |
弗雷德 ,从任何主机连接 |
” |
“%” |
任何用户,从任何主机连接 |
“弗雷德” |
“% .example.net” |
弗雷德 中的任意主机连接example.net 域 |
“弗雷德” |
“x.example. %” |
弗雷德 ,从x.example.net ,x.example.com ,x.example.edu ,等等;这可能没什么用 |
“弗雷德” |
“198.51.100.177” |
弗雷德 ,从有IP地址的主机连接198.51.100.177 |
“弗雷德” |
“198.51.100. %” |
弗雷德 中的任意主机连接198.51.100 C类子网 |
“弗雷德” |
“198.51.100.0/255.255.255.0” |
和前面的例子一样 |
中的多个行中,入站连接的客户端主机名和用户名可能匹配用户
表格前面的一组示例演示了这一点:显示的几个条目与来自的连接匹配h1.example.net
通过弗雷德
.
当可能存在多个匹配时,服务器必须确定使用其中的哪一个。解决方法如下:
每当服务器读取
用户
表放入内存中,它对行进行排序。当客户端尝试连接时,服务器会按顺序查看这些行。
服务器使用与客户端主机名和用户名匹配的第一行。
服务器使用排序规则对最特定的行进行排序宿主
值:
文字IP地址和主机名是最具体的。
字面IP地址的专一性不受它是否有网络掩码的影响,因此
198.51.100.13
而且198.51.100.0/255.255.255.0
被认为是同样具体的。该模式
“%”
意味着”任何主机”而且最不具体。空字符串
”
也意味着”任何主机”但在这之后“%”
.
非tcp(套接字文件、命名管道和共享内存)连接被视为本地连接,并匹配的主机部分本地主机
如果有任何这样的帐户,或主机部分与通配符匹配本地主机
否则(例如,当地的%
,l %
,%
).
相同的行宿主
值按最具体的顺序排列用户
第一个值。一个空白的用户
值意味着”任何用户”并且是最不特定的,所以对于相同的行宿主
值,非匿名用户排序优先于匿名用户。
对于具有相等特定的行宿主
而且用户
值,顺序是不确定的。
要了解这是如何工作的,假设用户
表是这样的:
+-----------+----------+- |主机|用户|…+-----------+----------+- | % | root |…杰弗里,|…| localhost | root |…| localhost | |…+-----------+----------+-
当服务器将表读入内存时,它使用刚才描述的规则对行进行排序。排序后的结果如下所示:
+-----------+----------+- |主机|用户|…+-----------+----------+- | 本地主机根| |……| localhost | |…杰弗里,|…| % | root |…+-----------+----------+-
当客户端尝试连接时,服务器查看排序的行并使用找到的第一个匹配。对于从本地主机
通过杰弗里
,表中有两行匹配:与宿主
而且用户
的值“localhost”
而且”
,和值为的“%”
而且“杰弗里。”
.的“localhost”
行按排序顺序首先出现,因此这是服务器使用的行。
这里还有一个例子。假设用户
表是这样的:
+----------------+----------+- | 主机用户| |…+----------------+----------+- | % | jeffrey |…| h1.example.net | |…+----------------+----------+-
排序后的表是这样的:
+----------------+----------+- | 主机用户| |…+----------------+----------+- | h1.example.net | |…杰弗里,|…+----------------+----------+-
第一行匹配来自的任何用户的连接h1.example.net
,而第二行匹配的连接为杰弗里
来自任何宿主。
一种常见的误解是认为,对于给定的用户名,当服务器试图为连接找到匹配时,首先使用显式地命名该用户的所有行。这是不对的。前面的示例说明了这一点,其中连接来自h1.example.net
通过杰弗里
第一行不是由包含“杰弗里。”
随着用户
列值,但按没有用户名的行。结果,杰弗里
作为匿名用户进行身份验证,即使他在连接时指定了用户名。
如果您能够连接到服务器,但您的特权不是您所期望的,那么您可能正在作为其他帐户进行身份验证。要了解服务器用于身份验证的帐户,请使用CURRENT_USER ()
函数。(见第12.16节“信息功能”)。它返回一个值
格式,表示user_name
@host_name
用户
而且宿主
匹配的值用户
表行。假设杰弗里
连接并发出以下查询:
mysql> SELECT当前用户()+----------------+ | CURRENT_USER () | +----------------+ | @ 本地主机 | +----------------+
这里显示的结果表明匹配用户
表行有一个空白用户
列值。换句话说,服务器正在处理杰弗里
作为匿名用户。
诊断身份验证问题的另一种方法是打印用户
表并手工排序,以查看在哪里进行了第一个匹配。