MySQL 提供了两个身份验证插件,它们实现了用户账户密码的 SHA-256 哈希处理:
-
sha256_password
:实现基本的 SHA-256 身份验证。 -
caching_sha2_password
:实现 SHA-256 身份验证(类似于sha256_password
),但是在服务器端使用缓存以提高性能,并具有更广泛的适用性。
本节描述原始的非缓存 SHA-2 身份验证插件。有关缓存插件的信息,请参阅 第 8.4.1.2 节,“缓存 SHA-2 可插拔身份验证”。
在 MySQL 8.3 中,caching_sha2_password
是默认的身份验证插件,而不是 mysql_native_password
(已弃用)。有关服务器操作和与客户端和连接器的兼容性的影响,请参阅 caching_sha2_password 作为首选身份验证插件。
因为 caching_sha2_password
是 MySQL 8.3 的默认身份验证插件,并提供了 sha256_password
身份验证插件的所有功能,因此 sha256_password
已弃用;预计在未来版本的 MySQL 中删除。使用 sha256_password
身份验证的 MySQL 帐户应该迁移到使用 caching_sha2_password
。
要使用 sha256_password
插件连接到服务器,需要使用 TLS 连接或支持密码交换的未加密连接,详见本节后面的描述。无论哪种方式,sha256_password
插件都使用 MySQL 的加密功能。请参阅 第 8.3 节,“使用加密连接”。
在名称 sha256_password
中,“sha256” 指的是插件使用的 256 位摘要长度。在名称 caching_sha2_password
中,“sha2” 指的是 SHA-2 加密算法类别,其中 256 位加密是其中的一个实例。后一个名称选择留有余地,以便在不更改插件名称的情况下扩展可能的摘要长度。
以下表格显示了服务器端和客户端插件的名称。
表 8.18 SHA-256 身份验证插件和库名称
Plugin or File | Plugin or File Name |
---|---|
服务器端插件 | sha256_password |
客户端插件 | sha256_password |
库文件 | 无(插件是内置的) |
以下部分提供了特定于 SHA-256 可插拔身份验证的安装和使用信息:
有关 MySQL 中的可插拔身份验证的一般信息,请参阅 第 8.2.17 节,“可插拔身份验证”。
插件 sha256_password
存在于服务器端和客户端形式:
-
服务器端插件是内置于服务器的,不需要显式加载,也不能通过卸载来禁用。
-
客户端插件是内置于
libmysqlclient
客户端库中的,并且对链接到libmysqlclient
的任何程序都可用。
要设置使用 sha256_password
插件的账户,使用以下语句,其中 password
是所需的账户密码:
CREATE USER 'sha256user'@'localhost'
IDENTIFIED WITH sha256_password BY 'password';
服务器将 sha256_password
插件分配给账户,并使用 SHA-256 加密密码,存储这些值在 mysql.user
系统表的 plugin
和 authentication_string
列中。
前面的说明不假设 sha256_password
是默认身份验证插件。如果 sha256_password
是默认身份验证插件,可以使用更简单的 CREATE USER
语法。
要将服务器启动时的默认身份验证插件设置为 sha256_password
,请在服务器选项文件中添加以下行:
[mysqld]
default_authentication_plugin=sha256_password
这将导致 sha256_password
插件被用作新账户的默认插件。因此,可以创建账户并设置密码,而不需要明确指定插件:
CREATE USER 'sha256user'@'localhost' IDENTIFIED BY 'password';
将 default_authentication_plugin
设置为 sha256_password
的另一个结果是,为了使用其他插件创建账户,必须明确指定该插件。例如,要使用已弃用的 mysql_native_password
插件,请使用以下语句:
CREATE USER 'nativeuser'@'localhost'
IDENTIFIED WITH mysql_native_password BY 'password';
sha256_password
支持安全传输连接。sha256_password
还支持使用 RSA 加密密码交换在未加密连接上,如果 MySQL 使用 OpenSSL 编译,并且要连接的 MySQL 服务器配置了 RSA(使用后面部分的 RSA 配置过程)。
RSA 支持具有以下特征:
-
在服务器端,两个系统变量命名 RSA 私钥和公钥文件:
sha256_password_private_key_path
和sha256_password_public_key_path
。数据库管理员必须在服务器启动时设置这些变量,如果要使用的密钥文件名称不同于系统变量的默认值。 -
服务器使用
sha256_password_auto_generate_rsa_keys
系统变量来确定是否自动生成 RSA 密钥对文件。请参阅 第 8.3.3 节,“创建 SSL 和 RSA 证书和密钥”。 -
状态变量
Rsa_public_key
显示sha256_password
身份验证插件使用的 RSA 公钥值。 -
拥有 RSA 公钥的客户端可以在连接过程中与服务器进行 RSA 密钥对基于密码交换,如后面所述。
-
对于使用
sha256_password
身份验证和 RSA 公钥对基于密码交换的连接,服务器会将 RSA 公钥发送给客户端,如有需要。然而,如果客户端主机上有公钥的副本,客户端可以使用它来节省客户端/服务器协议中的一个往返:-
对于这些命令行客户端,请使用
--server-public-key-path
选项指定 RSA 公钥文件:mysql, mysqladmin, mysqlbinlog, mysqlcheck, mysqldump, mysqlimport, mysqlpump, mysqlshow, mysqlslap, mysqltest, mysql_upgrade。 -
对于使用 C API 的程序,请调用
mysql_options()
,将 RSA 公钥文件指定为MYSQL_SERVER_PUBLIC_KEY
选项的值。 -
对于副本,使用
CHANGE REPLICATION SOURCE TO
语句,带有SOURCE_PUBLIC_KEY_PATH
选项,指定 RSA 公钥文件。对于组复制,group_replication_recovery_get_public_key
系统变量具有相同的目的。
-
对于使用 sha256_password
插件的客户端,密码在连接到服务器时从不以明文形式暴露。密码传输的方式取决于是否使用安全连接或 RSA 加密:
-
如果连接是安全的,RSA 密钥对是不必要的,不会被使用。这适用于使用 TLS 加密的连接。密码以明文形式发送,但由于连接是安全的,因此无法被截获。
Note与
caching_sha2_password
不同,sha256_password
插件不将共享内存连接视为安全,即使共享内存传输默认情况下是安全的。 -
如果连接不是安全的,并且 RSA 密钥对可用,连接将保持未加密状态。这适用于未使用 TLS 加密的连接。RSA 只用于客户端和服务器之间的密码交换,以防止密码截获。当服务器收到加密的密码时,它将其解密。加密中使用了混淆来防止重复攻击。
-
如果没有使用安全连接,并且 RSA 加密不可用,连接尝试将失败,因为密码不能以明文形式发送。
要使用 RSA 密码加密与 sha256_password
,客户端和服务器都必须使用 OpenSSL 编译,而不仅仅是其中之一。
假设 MySQL 已经使用 OpenSSL 编译,使用以下过程启用 RSA 密钥对的密码交换过程:
-
按照 第 8.3.3 节“创建 SSL 和 RSA 证书和密钥” 中的说明创建 RSA 私钥和公钥文件。
-
如果私钥和公钥文件位于数据目录中,并且分别命名为
private_key.pem
和public_key.pem
(默认值为sha256_password_private_key_path
和sha256_password_public_key_path
系统变量),服务器将自动在启动时使用它们。否则,要明确指定密钥文件的名称,请在服务器选项文件中设置系统变量的值。如果文件位于数据目录中,不需要指定完整的路径名:
[mysqld] sha256_password_private_key_path=myprivkey.pem sha256_password_public_key_path=mypubkey.pem
如果密钥文件不在数据目录中,或者要在系统变量值中明确指定其位置,请使用完整的路径名:
[mysqld] sha256_password_private_key_path=/usr/local/mysql/myprivkey.pem sha256_password_public_key_path=/usr/local/mysql/mypubkey.pem
-
重新启动服务器,然后连接到服务器并检查
Rsa_public_key
状态变量的值。显示的值将不同于这里显示的,但应该不是空的:mysql> SHOW STATUS LIKE 'Rsa_public_key'\G *************************** 1. row *************************** Variable_name: Rsa_public_key Value: -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDO9nRUDd+KvSZgY7cNBZMNpwX6 MvE1PbJFXO7u18nJ9lwc99Du/E7lw6CVXw7VKrXPeHbVQUzGyUNkf45Nz/ckaaJa aLgJOBCIDmNVnyU54OT/1lcs2xiyfaDMe8fCJ64ZwTnKbY2gkt1IMjUAB5Ogd5kJ g8aV7EtKwyhHb0c30QIDAQAB -----END PUBLIC KEY-----
如果值为空,服务器发现了密钥文件的问题。请检查错误日志以获取诊断信息。
在服务器配置了 RSA 密钥文件后,使用 sha256_password
插件的账户可以选择使用这些密钥文件连接到服务器。如前所述,这些账户可以使用安全连接(在这种情况下 RSA 不会被使用)或未加密的连接,该连接使用 RSA 进行密码交换。
$> mysql --ssl-mode=DISABLED -u sha256user -p
Enter password: password
例如,对于 sha256user
的连接尝试,服务器确定 sha256_password
是适当的身份验证插件,并调用它(因为在 CREATE USER
时指定了该插件)。插件发现连接不是加密的,因此需要使用 RSA 加密传输密码。在这种情况下,插件将 RSA 公钥发送给客户端,客户端使用它来加密密码,然后将结果返回给服务器。插件使用服务器端的 RSA 私钥来解密密码,并根据密码是否正确来接受或拒绝连接。
服务器将 RSA 公钥发送给客户端,如有必要。但是,如果客户端有一个包含服务器所需的 RSA 公钥的文件,可以使用 --server-public-key-path
选项指定该文件。
$> mysql --ssl-mode=DISABLED -u sha256user -p --server-public-key-path=file_name
Enter password: password
文件中公钥值,名为--server-public-key-path
选项,应该与服务器端文件中sha256_password_public_key_path
系统变量命名的文件中的密钥值相同。如果密钥文件包含有效的公钥值但值不正确,将发生访问被拒绝错误。如果密钥文件不包含有效的公钥,客户端程序无法使用它。在这种情况下,sha256_password
插件将公钥发送到客户端,就像没有指定--server-public-key-path
选项一样。
客户端用户可以通过两种方式获取RSA公钥:
-
数据库管理员可以提供公钥文件的副本。
-
可以以其他方式连接到服务器的客户端用户可以使用
SHOW STATUS LIKE 'Rsa_public_key'
语句,并将返回的密钥值保存在文件中。