MySQL设置管理员密码无法生效的案例一则

爱可生开源社区的这篇文章《技术分享 | MySQL 设置管理员密码无法生效一例》介绍了管理员账号密码不能生效的一则场景案例,一方面可以了解都有什么原因可能导致出现这种场景,另一方面就是对这种问题的排查路径,还是非常值得借鉴的,学习一下。

昨天某位客户咨询这样一个问题:他通过本地MySQL命令行连接数据库发现管理员不需要验证密码即可进行后续操作。为了查明原因,他尝试过修改管理员密码,依然无效。为了对比,他还特意创建了一个带密码的新用户,通过MySQL命令行可以正常进行密码验证。

此类问题大致会有如下几种原因:

  1. 此用户本身并没有设置密码。

  2. 配置文件里开启skip-grant-tables跳过授权表。

  3. 配置文件里有明文password选项来跳过密码。

  4. 用户的认证插件有可能使用auth_socket。

先来大致复现下这个问题。

现象如下:MySQL命令行客户端打印“hello world”不需要验证密码,

root@ytt-large:/home/ytt# mysql -e "select 'hello world'"
+-------------+
| hello world |
+-------------+
| hello world |
+-------------+

换个用户就验证密码后方可正常打印字符串,

root@ytt-large:/home/ytt# mysql -uadmin -e "select 'hello world'"
ERROR 1045 (28000): Access denied for user 'admin'@'localhost' (using password: NO)

root@ytt-large:/home/ytt# mysql -uadmin -p -e "select 'hello world'"
Enter password: 
+-------------+
| hello world |
+-------------+
| hello world |
+-------------+

尝试修改管理员密码,依然不需要验证密码即可执行命令:看结果好像是修改密码无效,

root@ytt-large:~# mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 35
Server version: 8.0.29 MySQL Community Server - GPL

...

mysql> alter user root@localhost identified by 'root';
Query OK, 0 rows affected (0.00 sec)

mysql> exit
Bye
root@ytt-large:/home/ytt# mysql -e "select 'hello world'"
+-------------+
| hello world |
+-------------+
| hello world |
+-------------+

接下来基于复现的场景以及开头想到的可能原因来逐步判断到底问题出在哪里。

1. 此用户本身并没有设置密码

这个原因可以快速排除掉。因为已经执行过一次alter user改密码的操作,所以不可能没有密码。

2. 配置文件里开启skip-grant-tables跳过授权表

这个原因也可以快速排除掉。如果是因为开启这个选项,那必定所有用户都不会验证密码,而不只是针对管理员账号本身。

3. 配置文件里有明文password选项来跳过密码

有可能是这个原因。可以用工具my_print_defaults来打印相关配置、或者直接手动检查配置文件有没有[client]、[mysql]等段里包含有password明文选项。例如,

root@ytt-large:/home/ytt# my_print_defaults /etc/mysql/my.cnf client mysql
--password=*****

结果确实是设置了password选项,但是仔细想想,有点站不住脚。如果是因为这个原因,那修改密码后,为什么依然不验证新密码?因此这个可能性也被排除掉。

4. 用户的认证插件有可能使用auth_socket

极有可能是这个原因。

插件auth_socket在MySQL官网全称为:Socket Peer-Credential Pluggable Authentication(套接字对等凭据可插拔的身份验证)。

官方文档地址:

https://dev.mysql.com/doc/refman/8.0/en/socket-pluggable-authentication.html

阅读官方文档后可以得出的结论为插件auth_socket不需要验证密码即可进行本地认证。他有两个认证条件,

  1. 客户端通过本地unix socket文件连接MySQL服务端。

2. 通过socket的选项SO_PEERCRED来获取运行客户端的OS用户名,随后判断OS用户名是否在mysql.user表里。

另外,想了解更多关于socket的选项SO_PEERCRED可以参考这个网址:

https://man7.org/linux/man-pages/man7/unix.7.html

我们接下来验证结论是否正确。查看当前登录用户是不是root@localhost,确认无疑,

root@ytt-large:/home/ytt# mysql  -e "select user(),current_user()"
   +----------------+----------------+
   | user()         | current_user() |
   +----------------+----------------+
   | root@localhost | root@localhost |
   +----------------+----------------+

检查mysql.user表记录:检查字段plugin、authentication_string(此字段有可能不为空),

mysql> select plugin,authentication_string from mysql.user where user = 'root' ;
   +-------------+-----------------------+
   | plugin      | authentication_string |
   +-------------+-----------------------+
   | auth_socket |                       |
   +-------------+-----------------------+
   1 row in set (0.01 sec)

确认管理员账号插件为auth_socket,难怪改密码无效。接下来把插件改为非auth_socket即可,

mysql> alter user root@localhost identified with mysql_native_password by 'root';
   Query OK, 0 rows affected (0.04 sec)

再次执行MySQL命令行:无密码正常报错,输入正确密码后执行成功,

root@ytt-large:/home/ytt# mysql -p -e "select 'hello world'"
   ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
   root@ytt-large:/home/ytt# mysql -proot -e "select 'hello world'"
   mysql: [Warning] Using a password on the command line interface can be insecure.
   +-------------+
   | hello world |
   +-------------+
   | hello world |
   +-------------+

因此,一般在遇到MySQL问题时,建议对MySQL系统函数、数据库内部对象等进行检索而不是直接打印字符串,有时候可能对快速定位问题原因有帮助。

MySQL一直给我的感觉就是很多功能和参数关系紧密,出问题的时候,很多场景都会和参数相关,参数越多,从控制的粒度,以及个性化的配置角度,就会更加方便,但同时就给MySQL精细化地使用提出了更高的要求。不同的数据库,由于站的角度可能不同,设计实现层面,还是有很多不一样的理解。

近期更新的文章:

华为matepad能成为你的笔记本电脑副屏?

Oracle中如何记录访问数据库的登录信息?

技术负责人如何搞垮一个团队?

最近碰到的一些问题

Oracle MySQL开源许可种种争议的解惑

文章分类和索引:

公众号1000篇文章分类和索引

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值