记录一次MySQL无法正常登录处理,及如何正确修改账户密码

285 阅读5分钟

一、前奏

正常部署项目,发现输入日志为: 提示为无法成功建立链接,链接被拒绝。本地客户端使用账户密码登录,显示 Access denied for user 'root'@'localhost' (using password: YES)

image.png

遂使用Navicat 测试远程链接,发现亦不能正常连接,判断可能是密码修改后忘记,或被他人修改。遂进行密码修改操作。

当前版本为 myql8

二、测试修改密码

由于我们这里使用的账号为 root 账号,且密码已遗忘,需要使用 mysql 的无密码登录模式,进行登录,然后对密码进行修改。操作如下:

1.修改 my.cnf 配置文件

一般路径为 \etc\my.cnf 具体以自己安装位置为准。 添加

[mysqld] 
skip-grant-tables

示例如下:

datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock

log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

innodb_buffer_pool_size=1073741824
join_buffer_size=1048576
sort_buffer_size=1048576
max_heap_table_size=33554432
tmp_table_size=33554432
[mysqld]
skip-grant-tables

2.添加完成后手动重启 mysqld 服务

mysqld 是 mysql 的服务端程序。

这里以 centos7.9为例

sudo systemctl restart mysqld

重启成功后,直接使用如下命令可直接登录进mysql

mysql -uroot 

3. 将密码置空并设置新密码

use mysql
# 以下为设置root 的认证为空
update user set authentication_string = '' where user = 'root';

为什么不能在这里直接修改密码。

网上有很多说法,说是直接在这里修改密码就可以成功登录。 我靠,我都不知道那些抄袭的有没有试验过,让我们一起来看看user表中 ,authentication_string 这个字段是什么样的

mysql> select user,authentication_string from user;
+------------------+------------------------------------------------------------------------+
| user             | authentication_string                                                  |
+------------------+------------------------------------------------------------------------+
| mysql.infoschema | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED |
| mysql.session    | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED |
| mysql.sys        | $A$005$THISISACOMBINATIONOFINVALIDSALTANDPASSWORDTHATMUSTNEVERBRBEUSED |
| root             | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B                              |
+------------------+------------------------------------------------------------------------+

这里可以看到,authentication_string 是经过处理的一段字符串,而不是密码明文,你使用
update user set authentication_string = '123456' where user = 'root';
修改了,mysql 在校验的时候就通不过了,能修改成功就有鬼了。 so,将此处置空,在正常登录时无需输入密码即可直接登录。

可能会有人说以前的 password 关键字也可以,但是mysql 8中已删除该关键字,则其不可再使用。这里也提一下以前的旧方法。

UPDATE mysql.user SET authentication_string=PASSWORD('newpassword') WHERE User='root' AND Host='localhost';

4.正式开始修改密码

想要正常修改账户密码,需要使用 mysql 提供的修改机制。

ALTER USER 'root'@'localhost' IDENTIFIED BY 'yourpassword';
# 注意,如果这里你的root 账户主机为% 需要使用下面的语句
ALTER USER 'root'@'%' IDENTIFIED BY 'yourpassword';

但是由于 mysql 安全策略限制,我们不能在免密码的登录模式下对密码进行修改,否则会错。

所以我们这里要先退出免密码模式。
将第一步在my.cnf 中添加的skip-grant-tables删除即可。

image.png 然后使用命令重新启动mysqld服务即可。

sudo systemctl restart mysqld

执行mysql -u root -p登录数据库,提示输入密码时直接敲回车,刚刚已经将密码置空了。

好了,现在你已经成功进入mysql了,开始修改密码即可。

use mysql;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'yourpassword';
#使用 命令查看一下,确定已修改
mysql> select user,host,plugin,authentication_string from user;
+------------------+-----------+-----------------------+------------------------------------------------------------------------+
| user             | host      | plugin                | authentication_string                                                  |
+------------------+-----------+-----------------------+------------------------------------------------------------------------+
| root             | localhost | mysql_native_password | *8124124F1231429E1B                              |
+------------------+-----------+-----------------------+------------------------------------------------------------------------+
#记得最后使用 刷新一下权限
FLUSH PRIVILEGES;

这里可以看到密码已经发生变化。

以下为扩展内容

三、修改密码后的公钥问题。

image.png

Caused by: com.mysql.cj.exceptions.UnableToConnectException: Public Key Retrieval is not allowed
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_372]
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_372]
        at sun.reflect.DelegatingConstructorAccessorImpl.newIns

这个问题是因为从 mysql5.7后,mysql 就默认使用 caching_sha2_password 如果我们在修改密码时没有指定 插件,则默认使用的为该插件。

以下为查询资料

  1. mysql_native_password:这是MySQL 5.6和5.7的默认认证插件。它使用SHA1算法进行密码存储和验证,认证速度快,但安全性较低,因为SHA1已被认为不够安全且容易受到攻击 。此外,从MySQL 8.0.34开始,mysql_native_password插件已被弃用,并可能在将来的版本中被移除。
  2. caching_sha2_password:这是MySQL 8.0及以后版本的默认认证插件。它使用SHA256算法提供更安全的密码加密,并且引入了密码缓存机制,以提高认证性能。当密码的哈希值缓存在内存中时,可以使用基于SHA256的快速质询-响应机制进行认证。它还支持安全连接,如使用TLS或RSA密钥对进行密码交换 。
  3. sha256_password:这个插件使用SHA256算法进行密码加密,提供了比mysql_native_password更高的安全性,但相较于caching_sha2_password,它没有缓存机制,因此在性能上可能稍逊一筹 。
  4. mysql_clear_password:此插件允许以明文形式发送密码,主要用于客户端插件,可以与任何需要明文密码的服务器端插件一起使用,但安全性较低 。
  5. auth_socket:此插件通过UNIX套接字文件对本地主机的连接进行认证,适合于需要严格控制访问权限的场景 。
  6. 多因素认证(MFA) :MySQL 8.0.27引入了多因素认证功能,可以通过authentication_policy系统变量来管理,允许指定多重身份校验,提高安全性 。

解决方法

1.1修改插件方式为 mysql_native_password

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YourPassword';
#修改完记得刷新权限
FLUSH PRIVILEGES;

1.2 保留默认的 caching_sha2_password 方式,设置 ssl相关的配置。
添加allowPublicKeyRetrieval=true和**useSSL=false** 例如

jdbc:mysql://localhost:3306/db?allowPublicKeyRetrieval=true&useSSL=false

[引用自](MySQL Connection String Options for .NET/C# - MySqlConnector)