MySQL 提供了两个身份验证插件,它们实现了用户账户密码的 SHA-256 哈希处理:
-
sha256_password
:实现基本的 SHA-256 身份验证。 -
caching_sha2_password
:实现 SHA-256 身份验证(类似于sha256_password
),但是在服务器端使用缓存以提高性能,并具有更广泛的适用性。
本节描述缓存 SHA-2 身份验证插件。有关基本(非缓存)插件的信息,请参阅 第 8.4.1.3 节,“SHA-256 可插拔身份验证”。
在 MySQL 8.3 中,caching_sha2_password
是默认的身份验证插件,而不是 mysql_native_password
(已弃用)。有关此更改对服务器操作和服务器与客户端和连接器的兼容性的影响,请参阅 caching_sha2_password 作为首选身份验证插件。
要使用 caching_sha2_password
插件连接到服务器,您必须使用安全连接或支持使用 RSA 密钥对交换密码的未加密连接,如本节后面所述。无论哪种方式,caching_sha2_password
插件都使用 MySQL 的加密功能。请参阅 第 8.3 节,“使用加密连接”。
在名称 sha256_password
中,“sha256” 指的是插件使用的 256 位摘要长度。在名称 caching_sha2_password
中,“sha2” 指的是 SHA-2 加密算法类别,其中 256 位加密是其中的一个实例。后一个名称选择留有余地,以便将来可能的摘要长度扩展而不改变插件名称。
与 sha256_password
相比,caching_sha2_password
插件具有以下优势:
-
在服务器端,内存缓存启用了快速重新身份验证,以便用户在再次连接时可以快速重新身份验证。
-
无论 MySQL 链接的是哪个 SSL 库,RSA 基于密码交换都是可用的。
-
支持使用 Unix 套接字文件和共享内存协议的客户端连接。
以下表格显示了服务器端和客户端的插件名称。
表 8.17 SHA-2 身份验证插件和库名称
Plugin or File | Plugin or File Name |
---|---|
服务器端插件 | caching_sha2_password |
客户端插件 | caching_sha2_password |
库文件 | 无(插件是内置的) |
以下部分提供了缓存 SHA-2 可插拔身份验证的安装和使用信息:
有关 MySQL 中可插拔身份验证的一般信息,请参阅 第 8.2.17 节,“可插拔身份验证”。
插件 caching_sha2_password
存在于服务器和客户端形式:
-
服务器端插件是内置的, 无需显式加载,且无法通过卸载来禁用。
-
客户端插件是内置在
libmysqlclient
客户端库中的,且可供任何链接到libmysqlclient
的程序使用。
服务器端插件使用 sha2_cache_cleaner
审核插件作为帮助器来执行密码缓存管理。 sha2_cache_cleaner
,像 caching_sha2_password
一样,是内置的,无需安装。
要设置使用 caching_sha2_password
插件的 SHA-256 密码哈希的账户,请使用以下语句,其中 password
是所需的账户密码:
CREATE USER 'sha2user'@'localhost'
IDENTIFIED WITH caching_sha2_password BY 'password';
服务器将 caching_sha2_password
插件分配给账户,并使用 SHA-256 加密密码,存储这些值在 mysql.user
系统表的 plugin
和 authentication_string
列中。
前面的说明不假设 caching_sha2_password
是默认的身份验证插件。如果 caching_sha2_password
是默认的身份验证插件,可以使用更简单的 CREATE USER
语法。
要将服务器的默认身份验证插件设置为 caching_sha2_password
,请在服务器选项文件中添加以下行:
[mysqld]
default_authentication_plugin=caching_sha2_password
这将导致 caching_sha2_password
插件被用作新账户的默认插件。因此,可以创建账户并设置密码,而不需要明确指定插件:
CREATE USER 'sha2user'@'localhost' IDENTIFIED BY 'password';
将 default_authentication_plugin
设置为 caching_sha2_password
的另一个结果是,为了使用其他插件创建账户,必须明确指定该插件。例如,要使用已弃用的 mysql_native_password
插件,请使用以下语句:
CREATE USER 'nativeuser'@'localhost'
IDENTIFIED WITH mysql_native_password BY 'password';
caching_sha2_password
支持通过安全传输的连接。如果按照后面部分的 RSA 配置过程,它还支持使用 RSA 在未加密连接上交换加密密码。RSA 支持具有以下特征:
-
在服务器端,两个系统变量命名 RSA 私钥和公钥文件:
caching_sha2_password_private_key_path
和caching_sha2_password_public_key_path
。数据库管理员必须在服务器启动时设置这些变量,如果要使用的密钥文件的名称不同于系统变量的默认值。 -
服务器使用
caching_sha2_password_auto_generate_rsa_keys
系统变量来确定是否自动生成 RSA 密钥对文件。请参阅 第 8.3.3 节,“创建 SSL 和 RSA 证书和密钥”。 -
状态变量
Caching_sha2_password_rsa_public_key
显示caching_sha2_password
身份验证插件使用的 RSA 公钥值。 -
在连接过程中,拥有RSA公钥的客户端可以与服务器进行基于RSA密钥对的密码交换,如后面所述。
-
对于使用
身份验证的账户连接,服务器默认不将RSA公钥发送给客户端。客户端可以使用客户端副本的公钥,或者从服务器请求公钥。 使用可信的本地公钥副本可以使客户端避免客户端/服务器协议中的一个来回,并且比从服务器请求公钥更安全。在另一方面,从服务器请求公钥更方便(不需要管理客户端文件),并且在安全的网络环境中可能是可接受的。
-
对于命令行客户端,使用
--server-public-key-path
选项指定RSA公钥文件。使用--get-server-public-key
选项从服务器请求公钥。以下程序支持这两个选项:mysql, mysqlsh, mysqladmin, mysqlbinlog, mysqlcheck, mysqldump, mysqlimport, mysqlpump, mysqlshow, mysqlslap, mysqltest, mysql_upgrade。 -
对于使用 C API 的程序,调用
mysql_options()
函数,传递MYSQL_SERVER_PUBLIC_KEY
选项和文件名,以指定 RSA 公钥文件,或者传递MYSQL_OPT_GET_SERVER_PUBLIC_KEY
选项,以从服务器请求公钥。 -
对于副本,使用
CHANGE REPLICATION SOURCE TO
语句,带有SOURCE_PUBLIC_KEY_PATH
选项,以指定 RSA 公钥文件,或者带有GET_SOURCE_PUBLIC_KEY
选项,以从源请求公钥。对于组复制,group_replication_recovery_public_key_path
和group_replication_recovery_get_public_key
系统变量具有相同的作用。
在所有情况下,如果指定了有效的公钥文件选项,它将优先于从服务器请求公钥的选项。
-
对于使用 caching_sha2_password
插件的客户端,密码从不以明文形式暴露在连接到服务器时。密码传输的方式取决于是否使用安全连接或 RSA 加密:
-
如果连接是安全的,RSA 密钥对是不必要的,不会被使用。这适用于使用 TLS 加密的 TCP 连接,以及 Unix 套接字文件和共享内存连接。密码以明文形式发送,但由于连接是安全的,因此无法被窃听。
-
如果连接不是安全的,RSA 密钥对将被使用。这适用于未使用 TLS 加密的 TCP 连接和命名管道连接。RSA 只用于客户端和服务器之间的密码交换,以防止密码窃听。当服务器接收到加密的密码时,它将其解密。加密中使用了混淆,以防止重复攻击。
要启用 RSA 密钥对在客户端连接过程中的使用,请按照以下步骤进行:
-
按照 第 8.3.3 节,「创建 SSL 和 RSA 证书和密钥」 中的说明,创建 RSA 私钥和公钥文件对。
-
如果私钥和公钥文件位于数据目录中,并命名为
private_key.pem
和public_key.pem
(默认值为caching_sha2_password_private_key_path
和caching_sha2_password_public_key_path
系统变量),服务器将自动在启动时使用它们。否则,要明确指定密钥文件,请在服务器选项文件中设置系统变量为密钥文件名。如果文件位于服务器数据目录中,无需指定完整路径名:
[mysqld] caching_sha2_password_private_key_path=myprivkey.pem caching_sha2_password_public_key_path=mypubkey.pem
如果密钥文件不在数据目录中,或者要在系统变量值中明确指定其位置,请使用完整路径名:
[mysqld] caching_sha2_password_private_key_path=/usr/local/mysql/myprivkey.pem caching_sha2_password_public_key_path=/usr/local/mysql/mypubkey.pem
-
如果您想更改
caching_sha2_password
在密码生成期间使用的哈希轮数,请设置caching_sha2_password_digest_rounds
系统变量。例如:[mysqld] caching_sha2_password_digest_rounds=10000
-
重新启动服务器,然后连接到它并检查
Caching_sha2_password_rsa_public_key
状态变量值。实际显示的值与这里显示的不同,但应该非空:mysql> SHOW STATUS LIKE 'Caching_sha2_password_rsa_public_key'\G *************************** 1. row *************************** Variable_name: Caching_sha2_password_rsa_public_key Value: -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDO9nRUDd+KvSZgY7cNBZMNpwX6 MvE1PbJFXO7u18nJ9lwc99Du/E7lw6CVXw7VKrXPeHbVQUzGyUNkf45Nz/ckaaJa aLgJOBCIDmNVnyU54OT/1lcs2xiyfaDMe8fCJ64ZwTnKbY2gkt1IMjUAB5Ogd5kJ g8aV7EtKwyhHb0c30QIDAQAB -----END PUBLIC KEY-----
如果值为空,服务器发现了密钥文件的一些问题。检查错误日志以获取诊断信息。
在服务器配置了 RSA 密钥文件后,使用 caching_sha2_password
插件进行身份验证的帐户可以选择使用这些密钥文件连接到服务器。如前所述,这些帐户可以使用安全连接(在这种情况下不使用 RSA)或未加密的连接,使用 RSA 进行密码交换。假设使用未加密的连接。例如:
$> mysql --ssl-mode=DISABLED -u sha2user -p
Enter password: password
对于 sha2user
的连接尝试,服务器确定 caching_sha2_password
是适当的身份验证插件,并调用它(因为这是在 CREATE USER
时间指定的插件)。插件发现连接未加密,因此需要使用 RSA 加密传输密码。但是,服务器不将公钥发送给客户端,客户端也没有提供公钥,因此无法加密密码,连接失败:
ERROR 2061 (HY000): Authentication plugin 'caching_sha2_password'
reported error: Authentication requires secure connection.
要从服务器请求 RSA 公钥,请指定 --get-server-public-key
选项:
$> mysql --ssl-mode=DISABLED -u sha2user -p --get-server-public-key
Enter password: password
在这种情况下,服务器将RSA公钥发送给客户端,客户端使用它来加密密码并将结果返回给服务器。插件使用服务器端的RSA私钥来解密密码,并根据密码是否正确来接受或拒绝连接。
或者,如果客户端有一个包含服务器所需的RSA公钥的文件,可以使用--server-public-key-path
选项指定该文件:
$> mysql --ssl-mode=DISABLED -u sha2user -p --server-public-key-path=file_name
Enter password: password
在这种情况下,客户端使用公钥来加密密码并将结果返回给服务器。插件使用服务器端的RSA私钥来解密密码,并根据密码是否正确来接受或拒绝连接。
由--server-public-key-path
选项指定的文件中的公钥值应该与服务器端由caching_sha2_password_public_key_path
系统变量指定的文件中的密钥值相同。如果密钥文件包含一个有效的公钥值但该值不正确,将发生访问被拒绝错误。如果密钥文件不包含有效的公钥,客户端程序无法使用它。
客户端用户可以通过两种方式获取RSA公钥:
-
数据库管理员可以提供公钥文件的副本。
-
可以以其他方式连接到服务器的客户端用户可以使用
SHOW STATUS LIKE 'Caching_sha2_password_rsa_public_key'
语句并将返回的密钥值保存在文件中。
在服务器端,caching_sha2_password
插件使用内存缓存来加速之前连接的客户端的身份验证。缓存条目由账户名/密码哈希对组成。缓存的工作方式如下:
-
当客户端连接时,
caching_sha2_password
检查客户端和密码是否与某个缓存条目匹配。如果是,则身份验证成功。 -
如果没有匹配的缓存条目,插件将尝试使用
mysql.user
系统表中的凭据来验证客户端。如果成功,caching_sha2_password
将为客户端添加一个缓存条目。否则,身份验证失败并且连接被拒绝。
因此,当客户端第一次连接时,对mysql.user
系统表的身份验证将发生。当客户端随后连接时,缓存中的快速身份验证将发生。
密码缓存操作除了添加条目外,都是由 sha2_cache_cleaner
审核插件处理的,该插件代表 caching_sha2_password
执行这些操作:
-
它清除任何被重命名或删除的帐户的缓存条目,或者任何帐户的凭证或身份验证插件被更改。
-
它在执行
FLUSH PRIVILEGES
语句时清空缓存。 -
它在服务器关闭时清空缓存。(这意味着缓存不会在服务器重新启动时保持不变。)
缓存清除操作会影响后续客户端连接的身份验证要求。对于每个用户帐户,在以下操作后,第一个客户端连接必须使用安全连接(使用 TLS 凭证的 TCP 连接、Unix 套接字文件或共享内存)或基于 RSA 密钥对的密码交换:
-
帐户创建后。
-
帐户密码更改后。
-
在
RENAME USER
操作后。 -
在
FLUSH PRIVILEGES
操作后。
FLUSH PRIVILEGES
清空整个缓存,影响所有使用 caching_sha2_password
插件的帐户。其他操作清除特定的缓存条目,仅影响操作中的帐户。
一旦用户成功身份验证,帐户将被加入缓存,后续连接不再需要安全连接或 RSA 密钥对,直到另一个缓存清除事件发生时影响该帐户。(当缓存可以使用时,服务器使用不需要明文密码传输的挑战响应机制,不需要安全连接。)