身份认证插件

在使用客户端登录MySQL8.0 时,经常会遇到下面这个报错:

ERROR 2059 (HY000): Authentication plugin 'caching_sha2_password' cannot be loaded

ERROR 2061 (HY000): Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection.
  • mysql_native_password
  • caching_sha2_password
Note:
As of MySQL 8.0.34, the mysql_native_password authentication plugin is deprecated and subject to removal in a future version of MySQL.

-- 查看默认身份默认插件
show global variables like "%auth%";

-- 查看当前使用的身份认证插件
SELECT USER,PLUGIN FROM mysql.`user` ;
+------------------+-----------------------+
| USER             | PLUGIN                |
+------------------+-----------------------+
| mysql.infoschema | caching_sha2_password |
| mysql.session    | caching_sha2_password |
| mysql.sys        | caching_sha2_password |
| root             | caching_sha2_password |
+------------------+-----------------------+

--修改用户的身份认证插件
CREATE USER 'baiding01'@'%' IDENTIFIED BY '123456';

--会清空密码
ALTER USER 'baiding01'@'%' IDENTIFIED WITH mysql_native_password;
--正确修改身份认证插件
ALTER USER 'baiding01'@'%' IDENTIFIED WITH mysql_native_password BY 'password';

CREATE USER 'baiding01'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';

CREATE USER 'baiding01'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'password';

安全连接 SSL (Secure Socket Layer)

为了更方便支持安全连接,从mysql 5.7.28开始使用 OpenSSL 编译的 MySQL 服务在启动时会自动生成缺失的 SSL 和 RSA 证书及密钥文件(在datadir目录下)。

服务器端配置

SSL 证书

在启动时,如果启用了 auto_generate_certs 系统变量,未指定除--ssl之外的SSL选项,并且数据目录中缺少服务器端SSL文件,则服务器会自动在数据目录中生成服务器端和客户端的SSL证书和密钥文件。

文件 描述
server-cert.pem 服务器端的SSL证书文件。它包含了服务器的公钥以及由可信的证书颁发机构(CA)签发的身份验证信息。客户端会用它来验证服务器的身份,确保正在与之通信的是预期的服务器。
server-key.pem 服务器端的私钥文件。私钥必须保密,仅服务器知道。服务器使用它来解密客户端发送的加密数据,并对自己发送的数据进行加密。
client-cert.pem 客户端的SSL证书文件。如果SSL通信要求双向认证(即服务器也需要验证客户端的身份),这个证书就包含了客户端的公钥和身份验证信息。
client-key.pem 客户端的私钥文件。与服务器端的私钥类似,客户端的私钥也必须保密。客户端使用它来解密服务器发送的加密数据,并对自己发送的数据进行加密。
ca.pem 证书颁发机构(CA)的根证书文件。它包含了CA的公钥,用于验证由该CA签发的所有证书的真实性。在SSL通信中,服务器和客户端都会使用这个根证书来验证对方的证书是否有效。
ca-key.pem 证书颁发机构(CA)的私钥文件。CA使用这个私钥来对其签发的证书进行数字签名。这个文件必须非常安全,因为如果泄露,攻 击者可以伪造证书。
查看当前基础环境
--查看默认数据目录
ls -l *.pem


--查看SSL是否启用
mysql> show variables like '%ssl%';
+-------------------------------------+-----------------+
| Variable_name                       | Value           |
+-------------------------------------+-----------------+
| have_openssl                        | YES             |
| have_ssl                            | YES             |   # 启动ssl
| performance_schema_show_processlist | OFF             |
| ssl_ca                              | ca.pem          |
| ssl_capath                          |                 |
| ssl_cert                            | server-cert.pem |
| ssl_cipher                          |                 |
| ssl_crl                             |                 |
| ssl_crlpath                         |                 |
| ssl_key                             | server-key.pem  |
+-------------------------------------+-----------------+

或

mysql> SELECT * FROM performance_schema.tls_channel_status\G
*************************** 1. row ***************************
 CHANNEL: mysql_main
PROPERTY: Enabled
   VALUE: Yes
*************************** 2. row ***************************
 CHANNEL: mysql_main
PROPERTY: ssl_accept_renegotiates
   VALUE: 0
*************************** 3. row ***************************
 CHANNEL: mysql_main
PROPERTY: Ssl_accepts
   VALUE: 2
...
*************************** 29. row ***************************
 CHANNEL: mysql_admin
PROPERTY: Enabled
   VALUE: No
   
   
--查看当前连接是否加密
mysql> SHOW SESSION STATUS LIKE 'Ssl_cipher';
或
mysql> status 
或
mysql> \s

客户端配置

  • 使用未加密连接

    --默认root用户,使用sock文件登录,默认是非加密方式
    [mysql@db1 ~]$ /usr/local/mysql8038/bin/mysql -uroot -S /mysql/8038/tmp/mysql.sock
    root@(none)>\s
    --------------
    /usr/local/mysql8038/bin/mysql  Ver 8.0.38 for Linux on x86_64 (MySQL Community Server - GPL)
    
    Connection id:          13
    Current database:
    Current user:           root@localhost
    SSL:                    Not in use
    Current pager:          stdout
    
    --业务用户sha2user,使用sock文件登录,默认是非加密方式
    root@(none)> CREATE USER 'sha2user'@'%' IDENTIFIED BY 'passwd123';
    root@(none)> GRANT SELECT ON *.* TO 'sha2user'@'%';
    
    [mysql@db1 ~]$ /usr/local/mysql8038/bin/mysql -usha2user -ppasswd123  -S /mysql/8038/tmp/mysql.sock
    sha2user@(none)>\s
    --------------
    /usr/local/mysql/bin/mysql  Ver 14.14 Distrib 5.7.32-35, for Linux (x86_64) using  6.0
    
    Connection id:          14
    Current database:
    Current user:           sha2user@localhost
    SSL:                    Not in use
    
    --业务用户,使用IP+端口登录(之所以能登录成功,是因为利用了之前登录的缓存信息)。
    C:\Users>mysql -usha2user -ppasswd123  -h192.168.2.100 -P8038  --ssl-mode=DISABLED
    mysql> \s
    --------------
    mysql  Ver 8.3.0 for Win64 on x86_64 (MySQL Community Server - GPL)
    
    Connection id:          29
    Current database:
    Current user:           sha2user@192.168.2.1
    SSL:                    Not in use
    
    
    在服务器上清除用户的缓存信息
    root@(none)>flush privileges;
    
    在客户端使用非安全方式登录
    C:\Users>mysql -usha2user -ppasswd123  -h192.168.2.100 -P8038  --ssl-mode=DISABLED
    mysql: [Warning] Using a password on the command line interface can be insecure.
    ERROR 2061 (HY000): Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection.
    
    
  • 显示使用加密连接

    #--ssl-mode=PREFERRED  默认行为,client 端尝试使用加密进行连接,如果无法构建加密连接,则会退回到未加密的连接
    C:\Users>mysql -usha2user -ppasswd123  -h192.168.2.100 -P8038 --ssl-mode=PREFERRED
    mysql> \s
    --------------
    mysql  Ver 8.3.0 for Win64 on x86_64 (MySQL Community Server - GPL)
    Connection id:          38
    Current database:
    Current user:           sha2user@192.168.2.1
    SSL:                    Cipher in use is TLS_AES_128_GCM_SHA256
    Using delimiter:        ;
    
    
    #--ssl-mode=REQUIRED Client 端需要加密连接,如果无法构建连接,则 Client 端将失败
    C:\Users>mysql -usha2user -ppasswd123  -h192.168.2.100 -P8038 --ssl-mode=REQUIRED
    mysql> \s
    --------------
    mysql  Ver 8.3.0 for Win64 on x86_64 (MySQL Community Server - GPL)
    Connection id:          39
    Current database:
    Current user:           sha2user@192.168.2.1
    SSL:                    Cipher in use is TLS_AES_128_GCM_SHA256
    Using delimiter:        ;
    
    
    #--ssl-mode=VERIFY_CA,指定需要验证 CA 证书,因为这个 CA 证书是自签发的,所以不在浏览器和操作系统的可信任区,则必须要将 CA 证书拷贝到客户端,并指定 CA 证书文件
    C:\Users>mysql -usha2user -ppasswd123  -h192.168.2.100 -P8038  --ssl-ca=D:\SSL\ca.pem
    mysql> \s
    --------------
    mysql  Ver 8.3.0 for Win64 on x86_64 (MySQL Community Server - GPL)
    
    Connection id:          40
    Current database:
    Current user:           sha2user@192.168.2.1
    SSL:                    Cipher in use is TLS_AES_128_GCM_SHA256
    Using delimiter:        ;
    
    
    #对于使用 REQUIRE X509 子句创建的帐户,客户端必须指定 --ssl-cert 和 --ssl-key。
    CREATE USER 'baiding2024'@'%'  IDENTIFIED BY '123456' REQUIRE X509 ;
    GRANT SELECT ON *.* TO 'baiding2024'@'%';
    mysql -ubaiding2024   -h192.168.2.100 -P8038  --ssl-cert=D:\SSL\client-cert.pem --ssl-key=D:\SSL\client-key.pem
    
    
    参数 说明
    --ssl-mode PREFERRED 默认行为,client 端尝试使用加密进行连接,如果无法构建加密连接,则会退回到未加密的连接
    REQUIRED Client 端需要加密连接,如果无法构建连接,则 Client 端将失败
    DISABLED Client 端使用未加密的连接
    VERIFY_CA Client 端需要加密连接,并且还对 CA 证书进行验证
    VERIFY_IDENTITY Client 端需要加密的连接,并且还针对 CA 证书和其证书中的服务器主机名执行验证。主机名身份验证VERIFY_IDENTITY 不适用于由服务器自动创建或使用 mysql_ssl_rsa_setup 手动创建的自签名CA证书。

MySQL SSL 连接中的握手过程

  1. 客户端发起 ssl 连接请求;
  2. MySQL Server 发送数字证书 server-cert.pem 给客户端(server-cert.pem包含:服务器公钥、CA签名信息);
  3. 客户端使用CA 证书 ca.pem(由于这是 MySQL 自签名的CA证书,无法从操作系统的可信任区获取,所以事先必须在客户端本地保存 CA 证书文件)中的 CA 公钥解密 server-cert.pem 中的签名,进行验证;
  4. 验证通过后,生成对称密钥,使用 server-cert.pem 中的公钥加密“对称密钥”,发送给 MySQL Server;
  5. MySQL Server 使用自己保留的私钥 server-key.pem 解密,得到“对称密钥”;
  6. 接下来传输数据则使用“对称密钥”进加密和解密。

如果仅指定 --ssl-mode=REQUIRED,不指定 --ssl-mode=VERIFY_CA 或者 --ssl-mode=VERIFY_IDENTITY,则不需要步骤3。

强制客户端以加密方式登录

--启用变量 require_secure_transport
root@(none)>show global variables like "require_secure_transport";
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| require_secure_transport | OFF   |
+--------------------------+-------+
1 row in set (2.98 sec)

root@(none)>set global require_secure_transport=ON;
Query OK, 0 rows affected (0.20 sec)

root@(none)>show global variables like "require_secure_transport";
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| require_secure_transport | ON    |
+--------------------------+-------+
1 row in set (0.40 sec)

root@(none)>

# 在本机通过 mysql.sock 方式登录,默认是已非加密方式登录
[mysql@db1 ~]$ /usr/local/mysql8038/bin/mysql -uroot -S /mysql/8038/tmp/mysql.sock --ssl-mode=DISABLED
root@(none)>\s
--------------
Connection id:          50
Current database:
Current user:           root@localhost
SSL:                    Not in use


# --ssl-mode=DISABLED 以显示的非加密方式登录,无论是否存在登录缓存,直接抛出异常
C:\Users>mysql -ubaiding01 -p123456  -h192.168.2.100 -P8038 --ssl-mode=DISABLED
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 3159 (HY000): Connections using insecure transport are prohibited while --require_secure_transport=ON.

强制单独用户加密登录

-- REQUIRE SSL  用户只能已加密方式登录
mysql> CREATE USER 'baiding01'@'%' IDENTIFIED BY '123456' REQUIRE SSL ;
mysql> GRANT SELECT ON *.* TO 'baiding01'@'%';



-- REQUIRE X509  具有REQUIRE X509子句的用户,客户端必须指定--ssl-key 和--ssl-cert选项才能连接。
mysql> CREATE USER 'baiding02'@'%' IDENTIFIED BY '123456' REQUIRE X509 ;
mysql> GRANT SELECT ON *.* TO 'baiding02'@'%';

mysql -ubaiding2024   -h192.168.2.100 -P8038  --ssl-cert=D:\SSL\client-cert.pem --ssl-key=D:\SSL\client-key.pem

RSA密钥对交换密码的非加密连接

RSA 证书

sha256_password_auto_generate_rsa_keys or caching_sha2_password_auto_generate_rsa_keys 这两个系统变量是相关的,但它们控制的是自动生成RSA密钥对文件。

文件 变量 描述
public_key.pem caching_sha2_password_public_key_path 公钥文件,它包含了公钥,可以被任何人获取和使用。公钥的主要作用是加密数据或验证数字签名。在公钥加密中,只有对应的私钥才能解密用公钥加密的数据。
private_key.pem caching_sha2_password_private_key_path 私钥文件,它包含了私钥,必须严格保密,只有密钥的所有者才能使用。私钥的主要作用是解密用公钥加密的数据或生成数字签名。
#对于这次由 baiding01 发起的连接尝试,服务器判断 caching_sha2_password 是合适的认证插件并调用它(因为在创建用户时指定了该插件)。插件发现连接未加密,因此要求使用 RSA 加密来传输密码。然而,服务器并未将公钥发送给客户端,而客户端也未提供公钥,因此无法加密密码,连接失败。
mysql  -ubaiding01 -p123456 -h 192.168.2.100 -P8038 --ssl-mode=DISABLED 


mysql  -ubaiding01 -p123456 -h 192.168.2.100 -P8038 --ssl-mode=DISABLED --get-server-public-key


mysql  -ubaiding01 -p123456 -h 192.168.2.100 -P8038 --ssl-mode=DISABLED --server-public-key-path=file_name

总结

变量 身份认证插件 说明
--ssl=ON caching_sha2_password 支持加密登录 <br />支持非加密登陆 可以通过mysql.sock以非加密方式登录<br />可以利用登录缓存以非加密方式登录<br />可以使用RSA方式登录
--ssl=ON<br />--require_secure_transport caching_sha2_password 强制客户端以加密方式登录 可以通过mysql.sock以非加密方式登录
--ssl=ON<br />--REQUIRE SSL caching_sha2_password 针对单独用户强制以加密方式登录 只能以加密方式登录<br />即使通过sock方式也只能以加密方式登录