8.4.1.2 缓存 SHA-2 插件式认证
MySQL 提供了两个实现 SHA-256 加密的用户账户密码插件:
-
caching_sha2_password
:在服务器端使用缓存,提高性能,并具有更广泛的适用性。 -
sha256_password
:实现基本 SHA-256 认证。该插件已弃用,不要使用该认证插件。
本节描述缓存 SHA-2 认证插件。关于原始的非缓存(已弃用的)插件,请参阅第8.4.1.3节,“SHA-256 插件式认证”。
在 MySQL 8.4 中,caching_sha2_password
是默认的认证插件,而不是 mysql_native_password
(已弃用)。关于服务器操作和与客户端、连接器兼容性,请参阅缓存 SHA-2 密码插件为推荐认证插件。
使用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
插件具有这些优点:
-
在服务器端,内存缓存使得之前连接过的用户重新身份验证速度更快。
-
RSA密码交换无论MySQL链接的是哪种SSL库都可用。
-
支持使用Unix socket文件和共享内存协议的客户端连接。
以下表格显示了服务器和客户端插件名称。
表8.16 SHA-2身份验证插件和库名称
Plugin or File | Plugin or File Name |
---|---|
服务器端插件 | caching_sha2_password |
客户端插件 | caching_sha2_password |
库文件 | 无(插件内置) |
以下部分提供了 caching SHA-2 插件式认证的安装和使用信息:
关于 MySQL 的插件式认证的总体信息,请参见第 8.2.17 节,“插件式认证”。
安装 SHA-2 插件式认证
插件caching_sha2_password
在服务器和客户端都存在:
-
服务器端插件内置在服务器中,不需要显式加载,也不能通过卸载它来禁用。
-
客户端插件内置在
libmysqlclient
客户端库中,对任何使用libmysqlclient
的程序都可用。
服务器插件使用sha2_cache_cleaner
审计插件作为帮助来管理密码缓存。sha2_cache_cleaner
,像caching_sha2_password
一样,是内置的,不需要安装。
使用 SHA-2 插件式认证
要设置使用caching_sha2_password
插件进行 SHA-256 密码哈希的账户,使用以下语句,其中password
是所需账户密码:
CREATE USER 'sha2user'@'localhost'
IDENTIFIED WITH caching_sha2_password BY 'password';
服务器将caching_sha2_password
插件分配给账户,并使用 SHA-256 加密密码,存储这些值在plugin
和authentication_string
mysql.user
系统表的列中。
前面的指令假设caching_sha2_password
不是默认认证插件。如果caching_sha2_password
是默认认证插件,可以使用更简单的CREATE USER
语句:
CREATE USER 'sha2user'@'localhost' IDENTIFIED BY 'password';
默认插件由authentication_policy
系统变量的值确定;默认情况下使用caching_sha2_password
。
要使用不同的插件,必须使用IDENTIFIED WITH
指定。例如,要指定弃用的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私钥对密码交换。
-
对于使用
caching_sha2_password
和基于RSA密钥对的密码交换进行身份验证的连接,服务器默认不向客户端发送RSA公共密钥。客户端可以使用客户端副本中的所需公共密钥,也可以请求服务器提供公共密钥。使用可靠的本地公共密钥副本可以使客户端避免客户端/服务器协议的回环,更加安全。但是,请求服务器提供公共密钥更方便(不需要管理客户端文件),在安全网络环境中也可能是可接受的。
-
在命令行客户端中,使用
--server-public-key-path
选项指定RSA公共密钥文件。使用--get-server-public-key
选项从服务器请求公共密钥。以下程序支持这两个选项:mysql,mysqlsh,mysqladmin,mysqlbinlog,mysqlcheck,mysqldump,mysqlimport,mysqlshow,mysqlslap,mysqltest。 -
对于使用 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,系统变量group_replication_recovery_public_key_path
和group_replication_recovery_get_public_key
承担相同的作用。
在所有情况下,如果指定了有效公钥文件,优先于请求服务器公钥。
-
对于使用 caching_sha2_password
插件的客户端,连接到服务器时密码永远不会以明文形式暴露。密码传输方式取决于是否使用安全连接或 RSA 加密:
-
如果连接是安全的,RSA密钥对是多余的,不会被使用。这适用于使用TLS加密的TCP连接、Unix socket文件连接和共享内存连接。密码以明文发送,但因为连接是安全的,所以不能被窃听。
-
如果连接不是安全的,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 公钥的文件,可以使用--server-public-key-path
选项指定该文件:
$> mysql --ssl-mode=DISABLED -u sha2user -p --server-public-key-path=file_name
Enter password: password
在这种情况下,客户端使用公钥加密密码并将结果返回给服务器。插件使用服务器侧的私钥解密密码,并根据密码是否正确接受或拒绝连接。
文件名为--server-public-key-path
选项指定的公钥值应该与服务器端文件名为caching_sha2_password_public_key_path
系统变量指定的公钥值相同。如果密钥文件包含有效的公钥值但该值不正确,访问被拒绝错误发生。如果密钥文件不包含有效的公钥,客户端程序无法使用。
客户用户可以通过以下两种方式获得RSA公钥:
-
数据库管理员可以提供公钥文件副本。
-
可以连接到服务器的其他方式的客户用户可以使用
SHOW STATUS LIKE 'Caching_sha2_password_rsa_public_key'
语句并将返回的密钥值保存到文件中。
SHA-2 插件式认证缓存操作
在服务器端,caching_sha2_password
插件使用内存缓存来加速之前连接的客户端身份验证。缓存项由账户名/密码哈希对组成。缓存工作方式如下:
-
当客户端连接时,
caching_sha2_password
检查客户端和密码是否匹配某个缓存项。如果是,身份验证成功。 -
如果没有匹配的缓存项,插件尝试根据
mysql.user
系统表中的凭证对客户端进行验证。如果成功,caching_sha2_password
将添加客户端到哈希中。否则,身份验证失败并拒绝连接。
这样,当客户端首次连接时,会对mysql.user
系统表进行身份验证。随后连接时,身份验证速度更快,因为是从缓存中获取。
sha2_cache_cleaner
审计插件负责除了添加条目的其他密码缓存操作,对caching_sha2_password
进行这些操作:
-
它清除任何被重命名或删除的账户的缓存条目,或者账户的凭证或身份验证插件发生变化的账户。
-
当执行
FLUSH PRIVILEGES
语句时,它将清空缓存。 -
它在服务器关闭时清空缓存。 (这意味着缓存不持久化到服务器重启。)
缓存清除操作影响后续客户端连接的身份验证要求。对于每个用户账户,首次连接后任何以下操作都需要使用安全连接(使用TCP、TLS凭证、Unix socket文件或共享内存)或RSA密钥对密码交换:
-
在账户创建时。
-
在账户密码更改时。
-
在
RENAME USER
操作时。
FLUSH PRIVILEGES
清空整个缓存,影响所有使用caching_sha2_password
插件的账户。其他操作清除特定条目,仅影响相关账户。
用户成功身份验证后,账户将被缓存,后续连接不需要安全连接或RSA密钥对,直到另一个缓存清除事件影响该账户。 (当缓存可用时,服务器使用挑战-响应机制,不使用明文密码传输,不需要安全连接。)