MYSQL中host名 127.0.0.1和localhost的小陷阱

本文描述了因MySQL中用户表顺序导致的权限验证错误。当使用127.0.0.1登录时,由于localhost配置在前且密码为空,导致即使输入正确密码也会被拒绝。通过调整用户表中记录顺序解决了此问题。
昨天晚上重装了下虚拟机,遇到点mysql账号相关的麻烦事,纠结了一晚上,早上起来,终于解决了。

我一般都是ssh到虚拟机上,直接用控制台对mysql进行日常管理的,这里就会用到host名为localhost的www用户,为了方便,是没有进行密码设置的,密码为空。

而我的应用程序呢,一般是用的127.0.0.1这个host下的www用户,密码不为空。


mysql> select host,user,password from user;
+-----------+------+-------------------------------------------+
| host | user | password |
+-----------+------+-------------------------------------------+
| localhost | www | |
| 127.0.0.1 | www | *password |
+-----------+------+-------------------------------------------+


这时便出现了一个比较怪的问题:

当我以127.0.0.1这个host进行mysql登录的时候,不管是ssh控制台

mysql -h 127.0.0.1 -u www -p

还是用rails 应用程序连接,均报以下错误:

Mysql::Error: Access denied for user 'www'@'localhost' (using password: YES)

怎么回事呢?为什么会把我的127.0.0.1这个host解析成localhost呢?

明明我指定用127.0.0.1这个host登录,Mysql为什么偏要给我换成localhost呢

仔细看看上面那个mysql.user这个表,你就会发现。

同样是www用户,host为localhost的数据行在host为127.0.0.1的这条数据行的前面。

当mysql解析这个127.0.0.1的时候,他会把他当成localhost来使。所以就找到了第一行,不带密码的www@localhost,马上就进行认证,看密码符不符合,来确认是否进行连接。

不知道这个算不算mysql的事,当连接数据库进行认证的时候,他会从上至下遍历,找到第一条满足条件的host和user数据,然后返回进行密码校验。

www@localhost这条数据在www@127.0.0.1这条数据之上,所以不管你来的是localhost,还是127.0.0.1, mysql都将用第一条无密码的www@localhost去进行密码校验。

交换一下顺序就OK了


mysql> select host,user,password from user;
+-----------+------+-------------------------------------------+
| host | user | password |
+-----------+------+-------------------------------------------+
| 127.0.0.1 | www | *password |
| localhost | www | |
+-----------+------+-------------------------------------------+


以上仅是个人观点,如有不正确的地方,请指正。
MySQL 中,host 设置为% localhost 存在明显区别及不同作用。 ### 区别 - **匹配范围**:当用户从客户端请求登陆时,MySQL 授权表中的 Host 字段可使用通配符进行匹配。其中,%是一个通配符,能匹配任意主机,即允许任何 IP 地址的客户端连接到 MySQL 服务器;而 localhost 仅代表本地主机,意味着只有在 MySQL 服务器所在的本机上运行的客户端才能连接到该服务器[^2]。 - **连接验证方式**:在本机使用`mysql -hlocalhost`(等同于`mysql`不指定 -h)或`mysql -h127.0.0.1`方式连接数据库时,MySQL 的权限验证模块会采用不同的方式。使用 localhost 连接时,会以本地套接字(Unix 系统)或命管道(Windows 系统)的方式进行连接;而使用%时,若客户端不在本地,会通过网络连接进行验证。例如,当客户端 IP 为 192.168.1.100 尝试连接 MySQL 服务,设置 host 为%时可允许其连接,设置为 localhost 则会拒绝连接[^3]。 ### 作用 - **%的作用**:将 host 设置为%,可使 MySQL 服务器接受来自任何 IP 地址的客户端连接请求,常用于需要从多个不同位置访问数据库的场景,如企业的多个分支机构或云环境中多个不同服务器上的应用程序都需要访问该数据库。 - **localhost 的作用**:设置为 localhost 能增强数据库的安全性,因为只有在服务器本机上运行的程序才能访问数据库,可避免外部网络的非法访问,适合对安全性要求较高且仅本地程序需要访问数据库的场景,如本地开发环境或一些内部系统的数据库。 ### 示例 假设在 MySQL 的 user 表中有以下两条记录: ```plaintext | User | Host | Password | |------|---------|----------| | test | % | xxxxxxxx | | test | localhost | xxxxxxxx | ``` 当客户端在本地使用`mysql -utest -p`命令连接时,会匹配到 Hostlocalhost 的记录进行身份验证;当客户端从外部网络使用`mysql -h<服务器 IP> -utest -p`连接时,会匹配到 Host 为%的记录进行身份验证。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值