今天搭建一个测试环境时,遇到了一个很隐蔽的问题。有必要分享一下
| user | password | host |
+------+-------------------------------------------+--------------------+
| root | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B | localhost |1
| root | | db-2.photo.xxx.org |2
| root | | 127.0.0.1 |3
| root | | ::1 |4
| | | localhost |5
| | | db-2.photo.xxx.org |6
| sys | *xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | db-2.photo.xxx.org |7
...
...
如上图所示,这个里面存在着两个用户名为空的情况。然后问题就是由此而起。
在本机(服务器,db-2.photo.xxx.org) mysql -usys -ppass -h`hostname` 或者 mysql -usys -ppass -h`hostname -i` 都提示无法连接。此时配置文件里面没有 --skip-name-resolve这个参数(DNS解析用的)
而用户表里面明明有这个sys@db-2.photo.xxx.org 而且密码也对了啊?起初没有注意到这个空用户,没想到它的陷阱,搞了很久也没连上,后来只好请老大了,老大过来一看,直接drop user ''@db-2.photo.xxx.org(删掉这个空用户,老大V5),然后再连,OK 搞定。
这是什么原因呢?
因为mysql在验证权限的时候,首先是验证host列,如果host列在验证user列,再password列,而现在按照我之前的连接语句:按照host列首先找到第6行,然后发现这行的user列为空(空匹配所有用户名),所以匹配到了这条记录,然后发现这条记录的密码为空,而我的连接语句里面有密码,那么就会报错。
好了,你可能会说要是我在连接的时候 -h指定的是ip地址,而不是域名(db-2.photo.xxx.org)那么不就不会匹配到了这条记录么?但是我在前面说了--skip-name-resolve这个参数我没有指定,那么就会DNS解析,将域名解析成IP地址。所以还是会被匹配到的。
于是我的连接语句改为 mysql -usys -h`hostname -i` 或者 mysql -usys -h`hostname` 此时就可以连接成功,但是请注意,虽然可以连接成功,但是实际上这个连上去的用户多大权限,也就是空用户所具有的权限。
而且,我后来模拟的时候,将第6行的存放顺序(物理磁盘上)和第7行反过来(这个可以通过optimize 一下table,然后顺序插入两条用户记录解决,虽然不能说绝对的成功,因为插在磁盘上的哪个位置不是我们能控制的,但是除非你RP败坏,可能会出现后插入的记录在物理磁盘上反而在前面)然后再进行前面的连接测试 mysql -usys -ppass -h`hostname -i` 或者 mysql -usys -ppass -h`hostname`, ok没问题了。同时如果将上面的连接语句去掉 -p选项,那么就是密码错误,也不会再去判断第7行了(已经调换顺序的第7行)
所以解决办法就是:
1.刚装好mysql后就直接删除那个空用户
2.连接的时候,-h+ip连接,且在配置文件里面指定 --skip-name-resolve,这样同时还能消除DNS解析带来的性能影响
另外,如果直接指定了socket的话,也不会存在这个问题,此时连接就是通过socket,而不是tcp/ip。 同时,如果你在别的机器上连接肯定也没问题,因为空用户默认的host就是主机地址。
不明白mysql5.5为什么这样设计,在mysql5.1里面就没有这个空用户。
mysql空用户(user列为空)的陷阱
最新推荐文章于 2022-07-29 13:41:08 发布