一直以为MySQL
的访问控制规则是先匹配username
再去匹配host
,没想到不是这样的。如果MySQL
用户管理不当,可能出现实际登陆的用户与期望连接的用户不一致的情况。
在创建用户的时候,user
和host
都可以为空值。当host
为空值时,等同于%
,代表any hosts
。当user
为空值时,也会匹配any user
,但匹配上的用户会被当成no name
的匿名用户。
由于通配符的存在,当一个用户登陆的时候,username@host
形式的认证信息是可能在mysql.user
表中匹配到多行的,当这种情况发生时,MySQL 就必须判断该匹配哪一行。它是这样做的:
1. 只要 MySQL 将`mysql.user`表读入内存,就对它排序;
2. 当有链接尝试连入的时候,MySQL 就按顺序从内存读取`user`表的行;
3. MySQL 使用匹配 username@host 的第一行。
mysql.user
表排序的规则是most-specific Host values first
,即最具体的 host 值优先。字符的host
和ip
是most specific
的,其中 ip 的具体度不受它是否携带子网掩码影响,像198.51.100.13 and 198.51.100.0/255.255.255.0
就可以看成是同样specific
的。通配符%
是least specific
的,blank
值同样代表any host
,但排序在%
后面。
相同host
的按most-specific User values first
规则排序,如果是blank
值则是least specific
的。
相同具体读的host
和user
行排序是不确定的。
某个库的user
表如下:
+-----------+----------+-
| Host | User | ...
+-----------+----------+-
| % | root | ...
| % | jeffrey | ...
| localhost | root | ...
| localhost | | ...
+-----------+----------+-
排序后就是这样
+-----------+----------+-
| Host | User | ...
+-----------+----------+-
| localhost | root | ...
| localhost | | ...
| % | jeffrey | ...
| % | root | ...
+-----------+----------+-
如果正在尝试连接的是jeffrey@localhost
,那么在user
表中会有两行匹配:’’@localhost
和Jeffrey@%
。按照顺序 MySQL 选择的应该是’’@localhost
,因此这个链接会以一个匿名用户的身份登录而不是Jeffrey
。这往往很容易造成误解。
MySQL :: MySQL 5.6 Reference Manual :: 6.2.4 Access Control, Stage 1: Connection Verification