MySQL8 中文参考(二十六)

2024-06-26 13:51:01 浏览数 (2)

原文:docs.oracle.com/javase/tutorial/reallybigindex.html

8.2.20 账户锁定

原文:dev.mysql.com/doc/refman/8.0/en/account-locking.html

MySQL 支持使用ACCOUNT LOCKACCOUNT UNLOCK子句对用户账户进行锁定和解锁,用于CREATE USERALTER USER语句:

  • 在与CREATE USER一起使用时,这些子句指定新账户的初始锁定状态。如果没有任何子句,则账户将以未锁定状态创建。 如果启用了validate_password组件,则不允许创建没有密码的账户,即使该账户被锁定。参见第 8.4.3 节,“密码验证组件”。
  • 在与ALTER USER一起使用时,这些子句指定现有账户的新锁定状态。如果没有任何子句,��账户的锁定状态保持不变。 从 MySQL 8.0.19 开始,ALTER USER ... UNLOCK解锁由于登录失败次数过多而暂时锁定的任何账户。参见第 8.2.15 节,“密码管理”。

账户锁定状态记录在mysql.user系统表的account_locked列中。SHOW CREATE USER的输出指示账户是锁定还是未锁定。

如果客户端尝试连接到一个被锁定的账户,连接尝试将失败。服务器会增加Locked_connects状态变量,指示尝试连接到被锁定账户的次数,返回一个ER_ACCOUNT_HAS_BEEN_LOCKED错误,并在错误日志中写入一条消息:

代码语言:javascript复制
Access denied for user '*user_name*'@'*host_name*'.
Account is locked.

锁定账户不影响使用代理用户连接的能力,代理用户假定被锁定账户的身份。它也不影响执行具有指定被锁定账户的DEFINER属性的存储程序或视图的能力。也就是说,锁定账户不影响使用代理账户或存储程序或视图的能力。

账户锁定功能取决于mysql.user系统表中是否存在account_locked列。对于从 MySQL 版本旧于 5.7.6 的升级,请执行 MySQL 升级过程以确保该列存在。参见第三章,“升级 MySQL”。对于没有account_locked列的非升级安装,服务器将所有账户视为未锁定,使用ACCOUNT LOCKACCOUNT UNLOCK子句会产生错误。

8.2.21 设置帐户资源限制

原文:dev.mysql.com/doc/refman/8.0/en/user-resources.html

限制客户端使用 MySQL 服务器资源的一种方法是将全局max_user_connections系统变量设置为非零值。这限制了任何给定帐户可以建立的同时连接数,但不限制客户端连接后可以做的事情。此外,设置max_user_connections不会启用对个别帐户的管理。这两种类型的控制对 MySQL 管理员很重要。

为了解决这些问题,MySQL 允许对个别帐户使用这些服务器资源的限制:

  • 一个帐户每小时可以发出的查询次数
  • 一个帐户每小时可以发出的更新次数
  • 一个帐户每小时可以连接到服务器的次数
  • 一个帐户对服务器的同时连接数

客户端可以发出的任何语句都计入查询限制。只有修改数据库或表的语句才计入更新限制。

在这种情况下,“帐户”对应于mysql.user系统表中的一行。也就是说,连接根据适用于连接的user表行中的UserHost值进行评估。例如,帐户'usera'@'%.example.com'对应于user表中具有UserHost值为usera%.example.com的行,以允许useraexample.com域中的任何主机连接。在这种情况下,服务器将在此行中的资源限制集体应用于useraexample.com域中的任何主机发起的所有连接,因为所有这样的连接使用相同的帐户。

在 MySQL 5.0 之前,“帐户”是根据用户连接的实际主机进行评估的。可以通过使用--old-style-user-limits选项启动服务器来选择这种较旧的计算方法。在这种情况下,如果usera同时从host1.example.comhost2.example.com连接,服务器会将帐户资源限制分别应用于每个连接。如果usera再次从host1.example.com连接,服务器将与该主机的现有连接一起应用该连接的限制。

注意

在 MySQL 8.0.30 中,--old-style-user-limits选项已被弃用,并可能在将来的 MySQL 版本中被移除。在 MySQL 8.0.30 或更高版本中在命令行或选项文件中使用此选项会导致服务器发出警告。

要在创建帐户时为帐户建立资源限制,请使用CREATE USER语句。要修改现有帐户的限制,请使用ALTER USER。提供一个WITH子句,命名要限制的每个资源。每个限制的默认值为零(无限制)。例如,要创建一个新帐户,可以访问customer数据库,但只能以有限的方式访问,发出以下语句:

代码语言:javascript复制
mysql> CREATE USER 'francis'@'localhost' IDENTIFIED BY 'frank'
 ->     WITH MAX_QUERIES_PER_HOUR 20
 ->          MAX_UPDATES_PER_HOUR 10
 ->          MAX_CONNECTIONS_PER_HOUR 5
 ->          MAX_USER_CONNECTIONS 2;

限制类型不需要全部在WITH子句中命名,但命名的限制可以以任何顺序出现。每小时限制的值应为表示每小时计数的整数。对于MAX_USER_CONNECTIONS,限制是表示帐户同时连接数的整数。如果将此限制设置为零,则全局max_user_connections系统变量值确定同时连接数。如果max_user_connections也为零,则该帐户没有限制。

要修改现有帐户的限制,请使用ALTER USER。以下语句将francis的查询限制更改为 100:

代码语言:javascript复制
mysql> ALTER USER 'francis'@'localhost' WITH MAX_QUERIES_PER_HOUR 100;

该语句仅修改指定的限制值,不会对帐户进行其他更改。

要删除限制,请将其值设置为零。例如,要删除francis每小时连接次数限制,使用以下语句:

代码语言:javascript复制
mysql> ALTER USER 'francis'@'localhost' WITH MAX_CONNECTIONS_PER_HOUR 0;

如前所述,帐户的同时连接限制是根据MAX_USER_CONNECTIONS限制和max_user_connections系统变量确定的。假设全局max_user_connections值为 10,并且有三个帐户具有以下指定的各自资源限制:

代码语言:javascript复制
ALTER USER 'user1'@'localhost' WITH MAX_USER_CONNECTIONS 0;
ALTER USER 'user2'@'localhost' WITH MAX_USER_CONNECTIONS 5;
ALTER USER 'user3'@'localhost' WITH MAX_USER_CONNECTIONS 20;

user1的连接限制为 10(全局max_user_connections值),因为它的MAX_USER_CONNECTIONS限制为零。user2user3的连接限制分别为 5 和 20,因为它们具有非零的MAX_USER_CONNECTIONS限制。

服务器将帐户的资源限制存储在与帐户对应的user表行中。max_questionsmax_updatesmax_connections列存储每小时限制,max_user_connections列存储MAX_USER_CONNECTIONS限制。(参见第 8.2.3 节,“授权表”。)

当任何帐户对其任何资源的使用放置了非零限制时,资源使用计数会发生。

当服务器运行时,它会计算每个账户使用资源的次数。如果一个账户在最近一小时内达到了连接数限制,服务器将拒绝该账户的进一步连接,直到该小时结束。同样,如果账户达到了查询或更新次数限制,服务器将拒绝进一步的查询或更新,直到该小时结束。在所有这些情况下,服务器会发出适当的错误消息。

资源计数是按账户而不是按客户端进行的。例如,如果您的账户有一个查询限制为 50,您不能通过同时在服务器上建立两个客户端连接来将限制增加到 100。两个连接上发出的查询会被一起计算。

当前每小时资源使用计数可以全局重置所有账户,或者针对特定账户进行单独重置:

  • 要将当前计数重置为零以适用于所有账户,请发出一个FLUSH USER_RESOURCES语句。也可以通过重新加载授权表(例如,使用FLUSH PRIVILEGES语句或mysqladmin reload命令)来重置计数。
  • 可以通过再次设置任何限制值将单个账户的计数重置为零。指定一个与当前分配给账户的值相等的限制值。

每小时计数重置不会影响MAX_USER_CONNECTIONS限制。

所有计数在服务器启动时都从零开始。计数不会在服务器重新启动时保留。

对于MAX_USER_CONNECTIONS限制,如果账户当前已经打开了允许的最大连接数,则可能出现一个边界情况:快速断开连接然后立即重新连接可能会导致错误(ER_TOO_MANY_USER_CONNECTIONSER_USER_LIMIT_REACHED),如果服务器在重新连接发生时还没有完全处理断开连接。当服务器完成断开连接处理后,又可以再次允许另一个连接。

8.2.22 连接到 MySQL 时出现问题的故障排除

原文:dev.mysql.com/doc/refman/8.0/en/problems-connecting.html

如果尝试连接到 MySQL 服务器时遇到问题,以下内容描述了您可以采取的一些措施来纠正问题。

确保服务器正在运行。如果没有运行,客户端无法连接到它。例如,如果尝试连接到服务器失败,并显示以下消息之一,可能的原因之一是服务器未运行:

代码语言:javascript复制
$> mysql
ERROR 2003: Can't connect to MySQL server on '*host_name*' (111)
$> mysql
ERROR 2002: Can't connect to local MySQL server through socket
'/tmp/mysql.sock' (111)

可能是服务器正在运行,但您尝试使用与服务器监听的 TCP/IP 端口、命名管道或 Unix 套接字文件不同的端口。当您调用客户端程序时,指定--port选项以指示正确的端口号,或者指定--socket选项以指示正确的命名管道或 Unix 套接字文件。要找出套接字文件的位置,您可以使用以下命令:

代码语言:javascript复制
$> netstat -ln | grep mysql

确保服务器未配置为忽略网络连接,或者(如果您尝试远程连接)未配置为仅在其网络接口上本地监听。如果服务器启用了skip_networking系统变量,将不接受 TCP/IP 连接。如果服务器启用了bind_address系统变量设置为127.0.0.1,它只在回环接口上本地监听 TCP/IP 连接,不接受远程连接。

检查确保没有防火墙阻止访问 MySQL。您的防火墙可能根据正在执行的应用程序或 MySQL 用于通信的端口号(默认为 3306)进行配置。在 Linux 或 Unix 下,请检查您的 IP 表(或类似)配置,确保端口未被阻止。在 Windows 下,诸如 ZoneAlarm 或 Windows 防火墙等应用程序可能需要配置不要阻止 MySQL 端口。

授予权限表必须正确设置,以便服务器可以使用它们进行访问控制。对于某些发行版类型(例如 Windows 上的二进制发行版,或 Linux 上的 RPM 和 DEB 发行版),安装过程会初始化 MySQL 数据目录,包括包含授予权限表的mysql系统数据库。对于不执行此操作的发行版,您必须手动初始化数据目录。有关详细信息,请参见第 2.9 节,“安装后设置和测试”。

要确定是否需要初始化授权表,请查找数据目录下是否有一个mysql目录。(数据目录通常命名为datavar,位于您的 MySQL 安装目录下。)确保在mysql数据库目录中有一个名为user.MYD的文件。如果没有,请初始化数据目录。完成后启动服务器,您应该能够连接到服务器。

在全新安装后,如果尝试以不使用密码的方式作为root登录到服务器,则可能会收到以下错���消息。

代码语言:javascript复制
$> mysql -u root 
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)

这意味着在安装过程中已经分配了一个 root 密码,并且必须提供该密码。请查看 Section 2.9.4, “Securing the Initial MySQL Account”,了解密码可能是如何分配的,以及在某些情况下如何找到它。如果需要重置 root 密码,请查看 Section B.3.3.2, “How to Reset the Root Password”中的说明。找到或重置密码后,请再次以root身份登录,使用--password(或-p)选项:

代码语言:javascript复制
$> mysql -u root -p
Enter password:

然而,如果您使用mysqld --initialize-insecure初始化 MySQL(详见 Section 2.9.1, “Initializing the Data Directory”),服务器将允许您以root身份连接而无需密码。这是一个安全风险,因此您应该为root账户设置密码;请参阅 Section 2.9.4, “Securing the Initial MySQL Account”获取指导。

如果您将现有的 MySQL 安装升级到新版本,您是否执行了 MySQL 升级过程?如果没有,请执行。当添加新功能时,授权表的结构偶尔会发生变化,因此在升级后,您应始终确保您的表具有当前结构。有关说明,请参见 Chapter 3, Upgrading MySQL

如果客户端程序在尝试连接时收到以下错误消息,则表示服务器期望密码的格式比客户端能够生成的格式更新:

代码语言:javascript复制
$> mysql
Client does not support authentication protocol requested
by server; consider upgrading MySQL client

客户端程序使用在选项文件或环境变量中指定的连接参数。如果客户端程序在没有在命令行上指定默认连接参数时似乎发送了不正确的连接参数,请检查任何适用的选项文件和您的环境。例如,如果在运行一个没有任何选项的客户端时收到Access denied,请确保您没有在任何选项文件中指定旧密码!

您可以通过使用--no-defaults选项调用客户端程序来抑制选项文件的使用。例如:

代码语言:javascript复制
$> mysqladmin --no-defaults -u root version

客户端使用的选项文件列在第 6.2.2.2 节,“使用选项文件”中。环境变量列在第 6.9 节,“环境变量”中。

如果收到以下错误,则表示您正在使用不正确的root密码:

代码语言:javascript复制
$> mysqladmin -u root -p*xxxx* ver
Access denied for user 'root'@'localhost' (using password: YES)

即使您没有指定密码,但出现上述错误,这意味着某个选项文件中列出了不正确的密码。尝试如前一项所述的--no-defaults选项。

更改密码的信息,请参阅第 8.2.14 节,“分配帐户密码”。

如果您忘记或丢失了root密码,请参阅第 B.3.3.2 节,“如何重置根密码”。

localhost是您的本地主机名的同义词,也是客户端尝试连接的默认主机,如果您未明确指定主机。

您可以使用--host=127.0.0.1选项显式命名服务器主机。这将导致与本地mysqld服务器的 TCP/IP 连接。您还可以通过指定使用实际主机名的--host选项来使用 TCP/IP。在这种情况下,即使您在同一主机上运行客户端程序,主机名也必须在服务器主机上的user表行中指定。

“拒绝访问”错误消息告诉您尝试登录的用户、您尝试连接的客户端主机以及是否使用了密码。通常,您应该在user表中有一行与错误消息中给定的主机名和用户名完全匹配。例如,如果收到包含using password: NO的错误消息,则表示您尝试在没有密码的情况下登录。

如果尝试使用mysql -u *user_name*连接到数据库时出现“拒绝访问”错误,则可能存在user表的问题。通过执行mysql -u root mysql并发出以下 SQL 语句来检查:

代码语言:javascript复制
SELECT * FROM user;

结果应包括HostUser列与您的客户端主机名和 MySQL 用户名匹配的行。

如果在尝试从 MySQL 服务器运行的主机之外的主机连接时出现以下错误,则表示user表中没有Host值与客户端主机匹配的行:

代码语言:javascript复制
Host ... is not allowed to connect to this MySQL server

您可以通过为尝试连接时使用的客户端主机名和用户名设置一个帐户来解决此问题。

如果您不知道正在连接的机器的 IP 地址或主机名,应在user表中将Host列值设置为'%'。尝试从客户端机器连接后,使用SELECT USER()查询查看您实际连接的方式。然后将user表中的'%'更改为日志中显示的实际主机名。否则,您的系统将因为允许给定用户名的任何主机连接而变得不安全。

在 Linux 上,出现此错误的另一个原因可能是您使用的二进制 MySQL 版本是使用与您使用的glibc库不同版本编译的。在这种情况下,您应该升级操作系统或glibc,或者下载 MySQL 版本的源代码分发并自行编译。源 RPM 通常很容易编译和安装,因此这不是一个大问题。

如果尝试连接时指定了主机名,但出现未显示主机名或为 IP 地址的错误消息,则表示 MySQL 服务器在尝试将客户端主机的 IP 地址解析为名称时出现错误:

代码语言:javascript复制
$> mysqladmin -u root -p*xxxx* -h *some_hostname* ver
Access denied for user 'root'@'' (using password: YES)

如果尝试以root身份连接并收到以下错误,则表示您在user表中没有一个User列值为'root'的行,而mysqld无法解析客户端的主机名:

代码语言:javascript复制
Access denied for user ''@'unknown'

这些错误指示 DNS 问题。要修复它,请执行mysqladmin flush-hosts以重置内部 DNS 主机缓存。请参见第 7.1.12.3 节,“DNS 查找和主机缓存”。

一些永久解决方案包括:

  • 确定您的 DNS 服务器出了什么问题并加以修复。
  • 在 MySQL 授权表中指定 IP 地址而不是主机名。
  • 在 Unix 的/etc/hosts或 Windows 的windowshosts中为客户端机器名称添加条目。
  • 使用启用了skip_name_resolve系统变量启动mysqld
  • 使用--skip-host-cache选项启动mysqld
  • 在 Unix 上,如果服务器和客户端在同一台机器上运行,请连接到localhost。对于连接到localhost的连接,MySQL 程序尝试使用 Unix 套接字文件连接到本地服务器,除非指定了连接参数以确保客户端进行 TCP/IP 连接。有关更多信息,请参见第 6.2.4 节,“使用命令选项连接到 MySQL 服务器”。
  • 在 Windows 上,如果您在同一台机器上运行服务器和客户端,并且服务器支持命名管道连接,请连接到主机名.(句点)。连接到.使用命名管道而不是 TCP/IP。

如果mysql -u root有效,但mysql -h *your_hostname* -u root导致拒绝访问(其中your_hostname是本地主机的实际主机名),则可能在user表中没有为您的主机指定正确的名称。这里一个常见的问题是user表行中的Host值指定了一个未经验证的主机名,但您系统的名称解析例程返回了一个完全限定的域名(或反之)。例如,如果user表中有一个带有主机'pluto'的行,但您的 DNS 告诉 MySQL 您的主机名是'pluto.example.com',那么该行将无效。尝试向user表中添加一行,其中包含您主机的 IP 地址作为Host列值。(或者,您可以向user表中添加一个包含通配符的Host值的行(例如,'pluto.%')。但是,使用以%结尾的Host值是不安全的,建议使用!)

如果mysql -u *user_name*有效,但mysql -u *user_name* *some_db*无效,则您尚未为名为some_db的数据库授予给定用户的访问权限。

如果在服务器主机上执行mysql -u *user_name*有效,但在远程客户端主机上执行mysql -h *host_name* -u *user_name*无效,则您尚未为给定用户从远程主机启用对服务器的访问。

如果你无法弄清楚为什么会出现拒绝访问的情况,请从user表中删除所有Host值包含通配符(包含'%''_'字符)的行。一个非常常见的错误是插入一个新行,其中Host='%'User='*some_user*',认为这样可以允许你指定localhost从同一台机器连接。这样做不起作用的原因是默认权限包括一行Host='localhost'User=''。因为该行具有比'%'更具体的Host'localhost',所以在从localhost连接时会优先使用该行而不是新行!正确的做法是插入第二行,其中Host='localhost'User='*some_user*',或者删除Host='localhost'User=''的行。删除行后,请记得发出FLUSH PRIVILEGES语句以重新加载授权表。另请参阅 Section 8.2.6,“访问控制,阶段 1:连接验证”。

如果您能够连接到 MySQL 服务器,但在执行 SELECT ... INTO OUTFILELOAD DATA 语句时收到 Access denied 消息,那么您在 user 表中的行没有启用 FILE 权限。

如果您直接更改授权表(例如,使用 INSERTUPDATEDELETE 语句),而您的更改似乎被忽略,请记住您必须执行 FLUSH PRIVILEGES 语句或 mysqladmin flush-privileges 命令,以使服务器重新加载权限表。否则,您的更改在下次服务器重启之前不会生效。请记住,在使用 UPDATE 语句更改 root 密码后,直到刷新权限之前,您不需要指定新密码,因为服务器在那时还不知道您已更改密码。

如果您在会话中间发现权限似乎已更改,可能是 MySQL 管理员已更改了它们。重新加载授权表会影响新的客户端连接,但也会影响现有连接,如 第 8.2.13 节,“权限更改何时生效” 所示。

如果您在 Perl、PHP、Python 或 ODBC 程序中遇到访问问题,请尝试使用 mysql -u *user_name* *db_name*mysql -u *user_name* -p*password* *db_name* 连接到服务器。如果您能够使用 mysql 客户端连接,问题可能出在您的程序上,而不是访问权限上。(-p 和密码之间没有空格;您也可以使用 --password=*password* 语法来指定密码。如果您使用 -p--password 选项而没有密码值,MySQL 会提示您输入密码。)

为了测试目的,使用--skip-grant-tables选项启动mysqld服务器。然后您可以更改 MySQL 授权表,并使用SHOW GRANTS语句检查您的修改是否产生了预期效果。当您满意您的更改时,执行mysqladmin flush-privileges告诉mysqld服务器重新加载权限。这使您可以开始使用新的授权表内容,而无需停止和重新启动服务器。

如果一切都失败了,请使用调试选项(例如,--debug=d,general,query)启动mysqld服务器。这将打印有关尝试连接的主机和用户信息,以及有关每个发出的命令的信息。请参阅 Section 7.9.4, “The DBUG Package”。

如果您在 MySQL 授权表上遇到任何其他问题,并在MySQL 社区 Slack上提问,请始终提供 MySQL 授权表的转储。您可以使用mysqldump mysql命令转储表格。要提交错误报告,请参阅 Section 1.5, “How to Report Bugs or Problems”中的说明。在某些情况下,您可能需要使用--skip-grant-tables重新启动mysqld以运行mysqldump

8.2.23 基于 SQL 的账户活动审计

原文:dev.mysql.com/doc/refman/8.0/en/account-activity-auditing.html

应用程序可以使用以下准则执行基于 SQL 的审计,将数据库活动与 MySQL 账户关联起来。

MySQL 账户对应于mysql.user系统表中的行。当客户端成功连接时,服务器会将客户端验证为此表中的特定行。此行中的UserHost列值唯一标识账户,并对应于 SQL 语句中写入账户名称的'*user_name*'@'*host_name*'格式。

用于验证客户端的账户决定客户端拥有哪些权限。通常,可以调用CURRENT_USER()函数来确定客户端用户的账户是什么。其值是从账户的user表行的UserHost列构造的。

然而,在某些情况下,CURRENT_USER()值不对应于客户端用户,而对应于不同的账户。这发生在不基于客户端账户进行权限检查的情况下:

  • 使用SQL SECURITY DEFINER特性定义的存储过程(过程和函数)
  • 使用SQL SECURITY DEFINER特性定义的视图
  • 触发器和事件

在这些情境中,权限检查针对DEFINER账户进行,而CURRENT_USER()指的是该账户,而不是调用存储过程或视图的客户端账户或导致触发器激活的账户。要确定调用用户,可以调用USER()函数,该函数返回一个值,指示客户端提供的实际用户名和客户端连接的主机。然而,这个值不一定直接对应user表中的账户,因为USER()值从不包含通配符,而账户值(由CURRENT_USER()返回)可能包含用户名和主机名通配符。

例如,空用户名称匹配任何用户,因此''@'localhost'账户允许客户端以任何用户名作为本地主机的匿名用户连接。在这种情况下,如果客户端以本地主机的user1连接,USER()CURRENT_USER()返回不同的值:

代码语言:javascript复制
mysql> SELECT USER(), CURRENT_USER();
 ----------------- ---------------- 
| USER()          | CURRENT_USER() |
 ----------------- ---------------- 
| user1@localhost | @localhost     |
 ----------------- ---------------- 

账户的主机名部分也可以包含通配符。如果主机名包含'%''_'模式字符或使用网络掩码表示法,该账户可以用于从多个主机连接的客户端,并且CURRENT_USER()值不会指示哪一个。例如,账户'user2'@'%.example.com'可以被user2用于从example.com域中的任何主机连接。如果user2remote.example.com连接,USER()CURRENT_USER()返回不同的值:

代码语言:javascript复制
mysql> SELECT USER(), CURRENT_USER();
 -------------------------- --------------------- 
| USER()                   | CURRENT_USER()      |
 -------------------------- --------------------- 
| user2@remote.example.com | user2@%.example.com |
 -------------------------- --------------------- 

如果应用程序必须调用USER()进行用户审计(例如,如果它在触发器内部进行审计),但必须能够将USER()值与user表中的账户关联起来,则必须避免在UserHost列中包含通配符的账户。具体来说,不要允许User为空(这会创建一个匿名用户账户),也不要在Host值中允许模式字符或网络掩码表示法。所有账户必须具有非空的User值和字面的Host值。

关于前面的例子,''@'localhost''user2'@'%.example.com'账户应该被修改,不要使用通配符:

代码语言:javascript复制
RENAME USER ''@'localhost' TO 'user1'@'localhost';
RENAME USER 'user2'@'%.example.com' TO 'user2'@'remote.example.com';

如果user2必须能够从example.com域中的多个主机连接,应该为每个主机单独创建一个账户。

CURRENT_USER()USER()值中提取用户名称或主机名部分,请使用SUBSTRING_INDEX()函数:

代码语言:javascript复制
mysql> SELECT SUBSTRING_INDEX(CURRENT_USER(),'@',1);
 --------------------------------------- 
| SUBSTRING_INDEX(CURRENT_USER(),'@',1) |
 --------------------------------------- 
| user1                                 |
 --------------------------------------- 

mysql> SELECT SUBSTRING_INDEX(CURRENT_USER(),'@',-1);
 ---------------------------------------- 
| SUBSTRING_INDEX(CURRENT_USER(),'@',-1) |
 ---------------------------------------- 
| localhost                              |
 ---------------------------------------- 

8.3 使用加密连接

原文:dev.mysql.com/doc/refman/8.0/en/encrypted-connections.html

8.3.1 配置 MySQL 使用加密连接

8.3.2 加密连接 TLS 协议和密码

8.3.3 创建 SSL 和 RSA 证书和密钥

8.3.4 通过 SSH 从 Windows 远程连接到 MySQL

8.3.5 重用 SSL 会话

在 MySQL 客户端和服务器之间的未加密连接中,可以访问网络的人可以监视所有流量并检查在客户端和服务器之间发送或接收的数据。

当您必须以安全方式在网络上传输信息时,不接受未加密的连接。要使任何类型的数据不可读,请使用加密。加密算法必须包含安全元素,以抵抗许多已知攻击,例如更改加密消息的顺序或重复数据两次。

MySQL 支持使用 TLS(传输层安全性)协议在客户端和服务器之间进行加密连接。TLS 有时被称为 SSL(安全套接字层),但 MySQL 实际上不使用 SSL 协议进行加密连接,因为其加密较弱(参见 第 8.3.2 节,“加密连接 TLS 协议和密码”)。

TLS 使用加密算法确保可以信任通过公共网络接收的数据。它具有检测数据更改、丢失或重放的机制。TLS 还包含使用 X.509 标准进行身份验证的算法。

X.509 使得在互联网上识别某人成为可能。简单来说,应该有一个名为“证书颁发机构”(CA)的实体,为需要的任何人分配电子证书。证书依赖于具有两个加密密钥(公钥和秘密密钥)的非对称加密算法。证书所有者可以向另一方展示证书作为身份证明。证书由其所有者的公钥组成。使用此公钥加密的任何数据只能使用相应的秘密密钥解密,该密钥由证书所有者持有。

MySQL 支持使用 OpenSSL 提供加密连接。有关 OpenSSL 支持的加密协议和密码,请参阅 第 8.3.2 节,“加密连接 TLS 协议和密码”。

默认情况下,MySQL 实例在运行时链接到一个已安装的 OpenSSL 库,以支持加密连接和其他与加密相关的操作。您可以从源代码编译 MySQL,并使用WITH_SSL CMake 选项指定特定已安装的 OpenSSL 版本的路径或替代的 OpenSSL 系统包。在这种情况下,MySQL 会选择该版本。有关如何执行此操作的说明,请参见 Section 2.8.6, “Configuring SSL Library Support”。

从 MySQL 8.0.11 到 8.0.17,可以使用 wolfSSL 编译 MySQL 作为 OpenSSL 的替代方案。从 MySQL 8.0.18 开始,不再支持 wolfSSL,所有 MySQL 构建都使用 OpenSSL。

您可以使用Tls_library_version 系统状态变量在运行时检查 OpenSSL 库的版本,该变量从 MySQL 8.0.30 开始可用。

如果您使用一个版本的 OpenSSL 编译 MySQL,并希望在不重新编译的情况下更改为另一个版本,可以通过编辑动态库加载器路径(Unix 系统上的 LD_LIBRARY_PATH 或 Windows 系统上的 PATH)来实现。删除编译版本的 OpenSSL 路径,并添加替换版本的路径,在路径上任何其他 OpenSSL 库之前放置它。在启动时,当 MySQL 无法在路径上找到使用WITH_SSL 指定的 OpenSSL 版本时,它会使用路径上指定的第一个版本。

默认情况下,MySQL 程序尝试使用加密进行连接,如果服务器支持加密连接,则在无法建立加密连接时回退到未加密连接。有关影响加密连接使用的选项的信息,请参见 Section 8.3.1, “Configuring MySQL to Use Encrypted Connections” 和 Command Options for Encrypted Connections。

MySQL 按连接进行加密,并且对于给定用户的加密使用可以是可选的或强制的。这使您可以根据个别应用程序的要求选择加密或未加密连接。有关如何要求用户使用加密连接的信息,请参见 Section 15.7.1.3, “CREATE USER Statement” 中 CREATE USER 语句的 REQUIRE 子句的讨论。另请参阅 Section 7.1.8, “Server System Variables” 中 require_secure_transport 系统变量的描述。

在源服务器和副本服务器之间可以使用加密连接。参见第 19.3.1 节,“设置复制使用加密连接”。

有关在 MySQL C API 中使用加密连接的信息,请参见支持加密连接。

也可以在 SSH 连接到 MySQL 服务器主机时使用加密连接。例如,请参见第 8.3.4 节,“在 Windows 上通过 SSH 远程连接到 MySQL”。

8.3.1 配置 MySQL 使用加密连接

原文:dev.mysql.com/doc/refman/8.0/en/using-encrypted-connections.html

有几个配置参数可用于指示是否使用加密连接,并指定适当的证书和密钥文件。本节提供了有关为加密连接配置服务器和客户端的一般指导:

  • 用于加密连接的服务器端启动配置
  • 加密连接的服务器端运行时配置和监控
  • 用于加密连接的客户端端配置
  • 将加密连接配置为强制性

还可以在其他情境中使用加密连接,如这些附加部分中所讨论的:

  • 源服务器和副本复制服务器之间。参见 第 19.3.1 节,“设置复制以使用加密连接”。
  • 在组复制服务器之间。参见 第 20.6.2 节,“使用安全套接字层(SSL)保护组通信连接”。
  • 基于 MySQL C API 的客户端程序。参见 支持加密连接。

有关创建所需证书和密钥文件的说明,请参阅 第 8.3.3 节,“创建 SSL 和 RSA 证书和密钥”。

用于加密连接的服务器端启动配置

在服务器端,--ssl 选项指定服务器允许但不要求加密连接。此选项默认启用,因此不需要显式指定。

要求客户端使用加密连接连接,请启用 require_secure_transport 系统变量。参见 将加密连接配置为强制性。

服务器端的这些系统变量指定了服务器在允许客户端建立加密连接时使用的证书和密钥文件:

  • ssl_ca:证书颁发机构(CA)证书文件的路径名。(ssl_capath类似,但指定了 CA 证书文件的目录路径名。)
  • ssl_cert:服务器公钥证书文件的路径名。此证书可以发送给客户端,并根据其拥有的 CA 证书进行验证。
  • ssl_key:服务器私钥文件的路径名。

例如,要启用服务器进行加密连接,请在my.cnf文件中使用以下行启动它,根据需要更改文件名:

代码语言:javascript复制
[mysqld]
ssl_ca=ca.pem
ssl_cert=server-cert.pem
ssl_key=server-key.pem

要额外指定客户端必须使用加密连接,请启用require_secure_transport系统变量:

代码语言:javascript复制
[mysqld]
ssl_ca=ca.pem
ssl_cert=server-cert.pem
ssl_key=server-key.pem
require_secure_transport=ON

每个证书和密钥系统变量都指定了一个 PEM 格式的文件。如果需要创建所需的证书和密钥文件,请参阅第 8.3.3 节,“创建 SSL 和 RSA 证书和密钥”。使用 OpenSSL 编译的 MySQL 服务器可以在启动时自动生成缺失的证书和密钥文件。请参阅第 8.3.3.1 节,“使用 MySQL 创建 SSL 和 RSA 证书和密钥”。或者,如果您有 MySQL 源代码分发版,您可以使用其mysql-test/std_data目录中的演示证书和密钥文件测试您的设置。

服务器执行证书和密钥文件的自动发现。如果除了--ssl(可能还包括ssl_cipher)之外没有给出明确的加密连接选项来配置加密连接,服务器会尝试在启动时自动启用加密连接支持:

  • 如果服务器在数据目录中发现名为ca.pemserver-cert.pemserver-key.pem的有效证书和密钥文件,它会启用客户端的加密连接支持。(文件不一定是自动生成的;重要的是它们具有这些名称并且是有效的。)
  • 如果服务器在数据目录中找不到有效的证书和密钥文件,它会继续执行,但不支持加密连接。

如果服务器自动启用了加密连接支持,它会在错误日志中写下一条说明。如果服务器发现 CA 证书是自签名的,它会在错误日志中写下一个警告。(如果证书是由服务器自动创建或使用 mysql_ssl_rsa_setup 手动创建,则证书是自签名的。)

MySQL 还为服务器端提供了这些系统变量来控制加密连接:

  • ssl_cipher:连接加密的可允许密码列表。
  • ssl_crl:包含证书吊销列表的文件的路径名。(ssl_crlpath 类似,但指定了证书吊销列表文件的目录路径名。)
  • tls_versiontls_ciphersuites:服务器允许用于加密连接的加密协议和密码套件;参见 Section 8.3.2, “Encrypted Connection TLS Protocols and Ciphers”。例如,您可以配置 tls_version 来阻止客户端使用不太安全的协议。

如果服务器无法从服务器端加密连接控制的系统变量创建有效的 TLS 上下文,则服务器将在没有加密连接支持的情况下执行。

用于加密连接的服务器端运行时配置和监控

在 MySQL 8.0.16 之前,配置加密连接支持的 tls_*xxx*ssl_*xxx* 系统变量只能在服务器启动时设置。因此,这些系统变量确定服务器为所有新连接使用的 TLS 上下文。

从 MySQL 8.0.16 开始,tls_*xxx*ssl_*xxx* 系统变量是动态的,可以在运行时设置,而不仅仅是在启动时。如果使用 SET GLOBAL 进行更改,新值仅在服务器重新启动之前有效。如果使用 SET PERSIST 进行更改,新值也会延续到后续的服务器重新启动。参见 Section 15.7.6.1, “SET Syntax for Variable Assignment”。然而,对这些变量的运行时更改不会立即影响新连接的 TLS 上下文,后文将对此进行解释。

随着 MySQL 8.0.16 中的更改,使得可以在运行时更改与 TLS 上下文相关的系统变量,服务器还启用了对用于新连接的实际 TLS 上下文的运行时更新。例如,这种功能可能很有用,以避免重新启动运行时间过长以至于 SSL 证书已过期的 MySQL 服务器。

要创建初始 TLS 上下文,服务器使用启动时上下文相关系统变量的值。为了公开上下文值,服务器还初始化了一组相应的状态变量。以下表格显示了定义 TLS 上下文的系统变量以及公开当前活动上下文值的相应状态变量。

表 8.12 服务器主连接接口 TLS 上下文的系统和状态变量

系统变量名称

对应的状态变量名称

ssl_ca

Current_tls_ca

ssl_capath

Current_tls_capath

ssl_cert

Current_tls_cert

ssl_cipher

Current_tls_cipher

ssl_crl

Current_tls_crl

ssl_crlpath

Current_tls_crlpath

ssl_key

Current_tls_key

tls_ciphersuites

Current_tls_ciphersuites

tls_version

Current_tls_version

截至 MySQL 8.0.21,这些活动的 TLS 上下文值也作为性能模式 tls_channel_status 表中的属性公开,以及任何其他活动 TLS 上下文的属性。

要在运行时重新配置 TLS 上下文,请使用以下过程:

  1. 设置每个应更改为新值的与 TLS 上下文相关的系统变量。
  2. 执行ALTER INSTANCE RELOAD TLS。该语句会从 TLS 上下文相关系统变量的当前值重新配置活动的 TLS 上下文。它还会设置相关状态变量以反映新的活动上下文值。该语句需要CONNECTION_ADMIN权限。
  3. 在执行ALTER INSTANCE RELOAD TLS后建立的新连接将使用新的 TLS 上下文。现有连接不受影响。如果需要终止现有连接,请使用KILL语句。

每对系统和状态变量的成员可能由于重新配置过程的方式而暂时具有不同的值:

  • ALTER INSTANCE RELOAD TLS之前对系统变量的更改不会改变 TLS 上下文。在这一点上,这些更改对新连接没有影响,相应的上下文相关系统和状态变量可能具有不同的值。这使您可以对个别系统变量进行任何所需的更改,然后在所有系统变量更改完成后使用ALTER INSTANCE RELOAD TLS原子地更新活动的 TLS 上下文。
  • ALTER INSTANCE RELOAD TLS之后,相应的系统和状态变量具有相同的值。这种情况会一直持续,直到对系统变量进行下一次更改。

在某些情况下,仅通过ALTER INSTANCE RELOAD TLS可能足以重新配置 TLS 上下文,而无需更改任何系统变量。假设由ssl_cert指定的文件中的证书已过期。只需用非过期证书替换现有文件内容,并执行ALTER INSTANCE RELOAD TLS即可使新文件内容被读取并用于新连接。

截至 MySQL 8.0.21,服务器为管理连接接口实现了独立的连接加密配置。请参阅 Administrative Interface Support for Encrypted Connections。此外,ALTER INSTANCE RELOAD TLS 还通过 FOR CHANNEL 子句扩展,允许指定要重新加载 TLS 上下文的通道(接口)。请参阅 Section 15.1.5, “ALTER INSTANCE Statement”。没有状态变量来公开管理接口的 TLS 上下文,但是性能模式 tls_channel_status 表公开了主接口和管理接口的 TLS 属性。请参阅 Section 29.12.21.9, “The tls_channel_status Table”。

更新主接口的 TLS 上下文会产生以下影响:

  • 此更新更改了主连接接口上用于新连接的 TLS 上下文。
  • 此更新还会更改管理接口上用于新连接的 TLS 上下文,除非为该接口配置了某些非默认的 TLS 参数值。
  • 此更新不会影响其他已启用的服务器插件或组件(如 Group Replication 或 X Plugin)使用的 TLS 上下文:
    • 要将主接口重新配置应用于 Group Replication 的组通信连接,这些连接从服务器的与 TLS 上下文相关的系统变量中获取其设置,必须执行 STOP GROUP_REPLICATION,然后执行 START GROUP_REPLICATION 来停止并重新启动 Group Replication。
    • X Plugin 在插件初始化时初始化其 TLS 上下文,如 Section 22.5.3, “Using Encrypted Connections with X Plugin” 中所述。此上下文之后不会更改。

默认情况下,如果配置值不允许创建新的 TLS 上下文,则 RELOAD TLS 操作将出现错误并且不会生效。先前的上下文值将继续用于新连接。如果给定了可选的 NO ROLLBACK ON ERROR 子句并且无法创建新上下文,则不会发生回滚。相反,会生成警告,并且在适用语句的接口上为新连接禁用加密。

在连接接口上启用或禁用加密连接的选项仅在启动时生效。例如,--ssl--admin-ssl选项仅在启动时影响主要和管理接口是否支持加密连接。这些选项在运行时被忽略,对ALTER INSTANCE RELOAD TLS的操作没有影响。例如,您可以使用--ssl=OFF在主接口上禁用加密连接启动服务器,然后重新配置 TLS 并执行ALTER INSTANCE RELOAD TLS在运行时启用加密连接。

客户端端加密连接的配置

有关与建立加密连接相关的客户端选项的完整列表,请参阅加密连接的命令选项。

默认情况下,如果服务器支持加密连接,MySQL 客户端程序会尝试建立加密连接,进一步的控制可以通过--ssl-mode选项进行设置:

  • 在没有--ssl-mode选项的情况下,客户端尝试使用加密连接进行连接,如果无法建立加密连接,则退回到未加密连接。这也是在明确指定--ssl-mode=PREFERRED选项时的行为。
  • 使用--ssl-mode=REQUIRED,客户端需要一个加密连接,如果无法建立加密连接则失败。
  • 使用--ssl-mode=DISABLED,客户端使用一个未加密的连接。
  • 使用--ssl-mode=VERIFY_CA--ssl-mode=VERIFY_IDENTITY,客户端需要一个加密连接,并且还会对服务器 CA 证书进行验证,并且(使用VERIFY_IDENTITY)对其证书中的服务器主机名进行验证。

重要提示

默认设置--ssl-mode=PREFERRED如果其他默认设置未更改,则会产生加密连接。然而,为了防止复杂的中间人攻击,客户端验证服务器的身份非常重要。设置--ssl-mode=VERIFY_CA--ssl-mode=VERIFY_IDENTITY比默认设置更好,以帮助防止这种类型的攻击。VERIFY_CA使客户端检查服务器的证书是否有效。VERIFY_IDENTITY使客户端检查服务器的证书是否有效,并且使客户端检查客户端使用的主机名是否与服务器证书中的身份匹配。要实施这些设置之一,您必须首先确保服务器的 CA 证书可靠地对所有在您的环境中使用它的客户端可用,否则将导致可用性问题。因此,它们不是默认设置。

如果在服务器端启用了require_secure_transport系统变量以导致服务器要求加密连接,则尝试建立未加密连接将失败。请参阅将加密连接配置为强制性。

客户端端的以下选项标识客户端在与服务器建立加密连接时使用的证书和密钥文件。它们类似于服务器端使用的ssl_cassl_certssl_key系统变量,但--ssl-cert--ssl-key标识客户端的公钥和私钥:

  • --ssl-ca:证书颁发机构(CA)证书文件的路径名。如果使用此选项,必须指定与服务器使用的相同证书。(--ssl-capath类似,但指定 CA 证书文件目录的路径名。)
  • --ssl-cert:客户端公钥证书文件的路径名。
  • --ssl-key:客户端私钥文件的路径名。

为了相对于默认加密提供额外的安全性,客户端可以提供与服务器使用的 CA 证书匹配的证书,并启用主机名身份验证。这样,服务器和客户端都信任同一 CA 证书,并且客户端验证连接的主机是预期的主机:

  • 要指定 CA 证书,请使用--ssl-ca(或--ssl-capath),并指定--ssl-mode=VERIFY_CA
  • 若要启用主机名身份验证,请使用--ssl-mode=VERIFY_IDENTITY而不是--ssl-mode=VERIFY_CA

注意

使用VERIFY_IDENTITY进行主机名身份验证无法与服务器自动创建的自签名证书或使用mysql_ssl_rsa_setup手动创建的证书一起使用(参见第 8.3.3.1 节,“使用 MySQL 创建 SSL 和 RSA 证书和密钥”)。这些自签名证书不包含服务器名称作为通用名称值。

在 MySQL 8.0.12 之前,主机名身份验证也无法与使用通配符指定通用名称的证书一起使用,因为该名称与服务器名称逐字比较。

MySQL 还为客户端提供了这些选项来控制客户端端的加密连接:

  • --ssl-cipher: 连接加密的允许密码列表。
  • --ssl-crl: 包含证书吊销列表的文件路径名。(--ssl-crlpath类似,但指定证书吊销列表文件目录的路径名。)
  • --tls-version, --tls-ciphersuites: 允许的加密协议和密码套件;参见第 8.3.2 节,“加密连接 TLS 协议和密码”。

根据客户端使用的 MySQL 帐户的加密要求,客户端可能需要指定某些选项以使用加密连接到 MySQL 服务器。

假设您想使用没有特殊加密要求的帐户连接,或者使用包含REQUIRE SSL子句的CREATE USER语句创建的帐户。假设服务器支持加密连接,客户端可以使用没有--ssl-mode选项或明确的--ssl-mode=PREFERRED选项连接使用加密:

代码语言:javascript复制
mysql

或者:

代码语言:javascript复制
mysql --ssl-mode=PREFERRED

对于使用REQUIRE SSL子句创建的帐户,如果无法建立加密连接,则连接尝试将失败。对于没有特殊加密要求的帐户,如果无法建立加密连接,则尝试回退到未加密连接。为了防止回退并在无法获取加密连接时失败,请这样连接:

代码语言:javascript复制
mysql --ssl-mode=REQUIRED

如果帐户具有更严格的安全要求,则必须指定其他选项以建立加密连接:

对于使用REQUIRE X509子句创建的帐户,客户端必须至少指定--ssl-cert--ssl-key。此外,建议使用--ssl-ca(或--ssl-capath)以便验证服务器提供的公共证书。例如(在一行上输入命令):

代码语言:javascript复制
mysql --ssl-ca=ca.pem
      --ssl-cert=client-cert.pem
      --ssl-key=client-key.pem

对于使用REQUIRE ISSUERREQUIRE SUBJECT子句创建的帐户,加密要求与REQUIRE X509相同,但证书必须分别与帐户定义中指定的发行者或主题匹配。

有关REQUIRE子句的更多信息,请参见第 15.7.1.3 节,“CREATE USER Statement”。

MySQL 服务器可以生成客户端证书和密钥文件,客户端可以使用这些文件连接到 MySQL 服务器实例。请参见第 8.3.3 节,“创建 SSL 和 RSA 证书和密钥”。

重要提示

如果连接到 MySQL 服务器实例的客户端使用具有extendedKeyUsage扩展(X.509 v3 扩展)的 SSL 证书,则扩展密钥用途必须包括客户端身份验证(clientAuth)。如果 SSL 证书仅用于服务器身份验证(serverAuth)和其他非客户端证书目的,证书验证将失败,客户端连接到 MySQL 服务器实例将失败。MySQL Server 生成的 SSL 证书中没有extendedKeyUsage扩展(如第 8.3.3.1 节,“使用 MySQL 创建 SSL 和 RSA 证书和密钥”中所述),并且使用openssl命令创建的 SSL 证书遵循第 8.3.3.2 节,“使用 openssl 创建 SSL 证书和密钥”中的说明。如果使用其他方式创建的客户端证书,请确保任何extendedKeyUsage扩展包括客户端身份验证。

为了防止使用加密并覆盖其他--ssl-*xxx*选项,请使用--ssl-mode=DISABLED调用客户端程序:

代码语言:javascript复制
mysql --ssl-mode=DISABLED

要确定当前与服务器的连接是否使用加密,请检查 Ssl_cipher 状态变量的会话值。如果值为空,则连接未加密。否则,连接已加密,并且该值指示加密密码。例如:

代码语言:javascript复制
mysql> SHOW SESSION STATUS LIKE 'Ssl_cipher';
 --------------- --------------------------- 
| Variable_name | Value                     |
 --------------- --------------------------- 
| Ssl_cipher    | DHE-RSA-AES128-GCM-SHA256 |
 --------------- --------------------------- 

对于 mysql 客户端,另一种方法是使用 STATUSs 命令并检查 SSL 行:

代码语言:javascript复制
mysql> s
...
SSL: Not in use
...

或者:

代码语言:javascript复制
mysql> s
...
SSL: Cipher in use is DHE-RSA-AES128-GCM-SHA256
...
配置加密连接为强制性

对于一些 MySQL 部署,使用加密连接可能不仅仅是可取的,而是强制性的(例如,为了满足监管要求)。本节讨论了使您能够执行此操作的配置设置。这些控制级别可用:

  • 您可以配置服务器要求客户端使用加密连接进行连接。
  • 您可以调用单独的客户端程序要求加密连接,即使服务器允许但不要求加密。
  • 您可以配置单独的 MySQL 帐户仅在加密连接上可用。

要求客户端使用加密连接连接,请启用 require_secure_transport 系统变量。例如,在服务器的 my.cnf 文件中添加以下行:

代码语言:javascript复制
[mysqld]
require_secure_transport=ON

或者,要在运行时设置并持久化该值,请使用以下语句:

代码语言:javascript复制
SET PERSIST require_secure_transport=ON;

SET PERSIST 为运行中的 MySQL 实例设置一个值。它还保存该值,导致其在后续服务器重启时使用。参见 Section 15.7.6.1, “SET Syntax for Variable Assignment”。

启用 require_secure_transport 后,客户端连接到服务器需要使用某种形式的安全传输,服务器仅允许使用 SSL 的 TCP/IP 连接,或者使用套接字文件(在 Unix 上)或共享内存(在 Windows 上)的连接。服务器拒绝非安全连接尝试,这些尝试将因 ER_SECURE_TRANSPORT_REQUIRED 错误而失败。

要调用客户端程序,使其要求加密连接,无论服务器是否要求加密,请使用 --ssl-mode 选项值 REQUIREDVERIFY_CAVERIFY_IDENTITY。例如:

代码语言:javascript复制
mysql --ssl-mode=REQUIRED
mysqldump --ssl-mode=VERIFY_CA
mysqladmin --ssl-mode=VERIFY_IDENTITY

要配置一个 MySQL 帐户仅在加密连接上可用,请在创建帐户的 CREATE USER 语句中包含一个 REQUIRE 子句,指定您需要的加密特性。例如,要求加密连接和使用有效的 X.509 证书,使用 REQUIRE X509

代码语言:javascript复制
CREATE USER 'jeffrey'@'localhost' REQUIRE X509;

有关REQUIRE子句的更多信息,请参见第 15.7.1.3 节,“CREATE USER Statement”。

要修改没有加密要求的现有帐户,请使用ALTER USER语句。

8.3.2 加密连接 TLS 协议和密码

原文:dev.mysql.com/doc/refman/8.0/en/encrypted-connection-protocols-ciphers.html

MySQL 支持多个 TLS 协议和密码,并允许配置哪些协议和密码用于加密连接。还可以确定当前会话使用的协议和密码。

  • 支持的 TLS 协议
  • 移除对 TLSv1 和 TLSv1.1 协议的支持
  • 连接 TLS 协议配置
  • 连接密码配置
  • 连接 TLS 协议协商
  • 监视当前客户端会话的 TLS 协议和密码
支持的 TLS 协议

允许连接到给定 MySQL 服务器实例的协议集受多个因素影响,如下所示:

MySQL 服务器版本

  • 直到 MySQL 8.0.15,MySQL 支持 TLSv1、TLSv1.1 和 TLSv1.2 协议。
  • 从 MySQL 8.0.16 开始,MySQL 还支持 TLSv1.3 协议。要使用 TLSv1.3,MySQL 服务器和客户端应用程序必须使用 OpenSSL 1.1.1 或更高版本进行编译。从 MySQL 8.0.18 开始,Group Replication 组件支持 TLSv1.3(有关详细信息,请参见第 20.6.2 节,“使用安全套接字层(SSL)保护组通信连接”)。
  • 截至 MySQL 8.0.26 版本,TLSv1 和 TLSv1.1 协议已被弃用。这些协议版本较旧,分别于 1996 年和 2006 年发布,使用的算法较弱且过时。有关背景,请参考 IETF 备忘录Deprecating TLSv1.0 and TLSv1.1。
  • 截至 MySQL 8.0.28 版本,MySQL 不再支持 TLSv1 和 TLSv1.1 协议。从此版本开始,客户端不能使用协议设置为 TLSv1 或 TLSv1.1 进行 TLS/SSL 连接。有关更多详细信息,请参见移除对 TLSv1 和 TLSv1.1 协议的支持。

表 8.13 MySQL 服务器 TLS 协议支持

MySQL 服务器版本

支持的 TLS 协议

MySQL 8.0.15 及以下版本

TLSv1、TLSv1.1、TLSv1.2

MySQL 8.0.16 和 MySQL 8.0.17

TLSv1、TLSv1.1、TLSv1.2、TLSv1.3(不包括 Group Replication)

MySQL 8.0.18 到 MySQL 8.0.25

TLSv1、TLSv1.1、TLSv1.2、TLSv1.3(包括 Group Replication)

MySQL 8.0.26 和 MySQL 8.0.27

TLSv1(已弃用)、TLSv1.1(已弃用)、TLSv1.2、TLSv1.3

MySQL 8.0.28 及更高版本

TLSv1.2、TLSv1.3

SSL 库

如果 SSL 库不支持特定协议,MySQL 也不支持,以下讨论中指定该协议的任何部分都不适用。特别要注意的是,要使用 TLSv1.3,MySQL 服务器和客户端应用程序都必须使用 OpenSSL 1.1.1 或更高版本进行编译。MySQL 服务器在启动时检查 OpenSSL 的版本,如果低于 1.1.1,则会从与 TLS 版本相关的服务器系统变量的默认值中删除 TLSv1.3(tls_versionadmin_tls_versiongroup_replication_recovery_tls_version)。

MySQL 实例配置

可以在服务器端和客户端上配置允许的 TLS 协议,只包括受支持的 TLS 协议的子集。双方的配置必须至少包括一个共同的协议,否则连接尝试无法协商要使用的协议。有关详细信息,请参阅 连接 TLS 协议协商。

系统范围的主机配置

主机系统可能只允许某些 TLS 协议,这意味着即使 MySQL 本身允许它们,MySQL 连接也不能使用非允许的协议:

  • 假设 MySQL 配置允许 TLSv1、TLSv1.1 和 TLSv1.2,但您的主机系统配置只允许使用 TLSv1.2 或更高版本的连接。在这种情况下,即使 MySQL 配置允许它们,您也无法建立使用 TLSv1 或 TLSv1.1 的 MySQL 连接,因为主机系统不允许���们。
  • 如果 MySQL 配置允许 TLSv1、TLSv1.1 和 TLSv1.2,但您的主机系统配置只允许使用 TLSv1.3 或更高版本的连接,则根本无法建立 MySQL 连接,因为 MySQL 允许的任何协议都不被主机系统允许。

解决此问题的方法包括:

更改系统范围的主机配置以允许额外的 TLS 协议。请查阅操作系统文档以获取说明。例如,您的系统可能有一个包含以下行的 /etc/ssl/openssl.cnf 文件,以将 TLS 协议限制为 TLSv1.2 或更高版本:

代码语言:javascript复制
[system_default_sect]
MinProtocol = TLSv1.2

将值更改为较低的协议版本或None会使系统更加宽松。这种解决方法的缺点是允许较低(不太安全)的协议可能会产生不利的安全后果。

如果您无法或不愿更改主机系统的 TLS 配置,请将 MySQL 应用程序更改为使用主机系统允许的更高(更安全)的 TLS 协议。对于仅支持较低协议版本的旧版本 MySQL 可能无法实现此目标。例如,在 MySQL 5.6.46 之前,只支持 TLSv1 协议,因此即使客户端来自支持更高协议版本的新 MySQL 版本,尝试连接到早于 5.6.46 的服务器也会失败。在这种情况下,可能需要升级到支持额外 TLS 版本的 MySQL 版本。

不再支持 TLSv1 和 TLSv1.1 协议。

从 MySQL 8.0.28 开始,不再支持 TLSv1 和 TLSv1.1 连接协议。这些协议从 MySQL 8.0.26 开始被弃用。有关背景,请参考 IETF 备忘录Deprecating TLSv1.0 and TLSv1.1。建议使用更安全的 TLSv1.2 和 TLSv1.3 协议进行连接。TLSv1.3 要求 MySQL 服务器和客户端应用程序都使用 OpenSSL 1.1.1 进行编译。

不再支持 TLSv1 和 TLSv1.1 是因为这些协议版本过时,分别于 1996 年和 2006 年发布。使用的算法过于薄弱和过时。除非您使用非常旧的 MySQL Server 或连接器版本,否则不太可能使用 TLSv1.0 或 TLSv1.1 进行连接。MySQL 连接器和客户端默认选择可用的最高 TLS 版本。

在不支持 TLSv1 和 TLSv1.1 连接协议的版本中(从 MySQL 8.0.28 开始),包括 MySQL Shell 在内支持用于指定连接到 MySQL 服务器的 TLS 协议的--tls-version选项的客户端无法使用设置为 TLSv1 或 TLSv1.1 的协议进行 TLS/SSL 连接。如果客户端尝试使用这些协议进行连接,则对于 TCP 连接,连接将失败,并向客户端返回错误。对于套接字连接,如果--ssl-mode设置为REQUIRED,则连接将失败,否则将进行连接,但禁用 TLS/SSL。

从 MySQL 8.0.28 开始,服务器端的以下设置已更改:

  • 服务器的tls_versionadmin_tls_version系统变量的默认值不再包括 TLSv1 和 TLSv1.1。
  • Group Replication 系统变量group_replication_recovery_tls_version的默认值不再包括 TLSv1 和 TLSv1.1。
  • 对于异步复制,副本不能将与源服务器的连接协议设置为 TLSv1 或 TLSv1.1(CHANGE REPLICATION SOURCE TO 语句的 SOURCE_TLS_VERSION 选项)。

在 TLSv1 和 TLSv1.1 连接协议被弃用的版本中(MySQL 8.0.26 和 MySQL 8.0.27),如果它们包含在 tls_versionadmin_tls_version 系统变量的值中,并且客户端成功使用它们连接,则服务器会在错误日志中写入警告。如果在运行时设置弃用的协议并使用 ALTER INSTANCE RELOAD TLS 语句实现它们,也会返回警告。如果配置允许弃用的 TLS 协议,包括为与源服务器的连接指定 TLS 协议的副本和为分布式恢复连接指定 TLS 协议的 Group Replication 组成员,那么客户端不会发出警告。

更多信息,请参见 MySQL 8.0 是否支持 TLS 1.0 和 1.1?

连接 TLS 协议配置

在服务器端,tls_version 系统变量的值确定 MySQL 服务器允许加密连接使用的 TLS 协议。tls_version 值适用于来自客户端的连接、常规源/副本复制连接(其中此服务器实例是源)、Group Replication 组通信连接以及 Group Replication 分布式恢复连接(其中此服务器实例是捐赠者)。管理连接接口配置类似,但使用 admin_tls_version 系统变量(参见第 7.1.12.2 节,“管理连接管理”)。此讨论也适用于 admin_tls_version

tls_version 值是一个或多个逗号分隔的 TLS 协议版本列表,不区分大小写。默认情况下,此变量列出了编译 MySQL 和 MySQL 服务器发布所使用的 SSL 库支持的所有协议。因此,默认设置如表 8.14,“MySQL 服务器 TLS 协议默认设置”所示。

表 8.14 MySQL 服务器 TLS 协议默认设置

MySQL 服务器发布版本

tls_version 默认设置

MySQL 8.0.15 及以下版本

TLSv1,TLSv1.1,TLSv1.2

MySQL 8.0.16 和 MySQL 8.0.17

TLSv1,TLSv1.1,TLSv1.2,TLSv1.3 (使用 OpenSSL 1.1.1) TLSv1,TLSv1.1,TLSv1.2 (其他情况) Group Replication 不支持 TLSv1.3

MySQL 8.0.18 到 MySQL 8.0.25

TLSv1,TLSv1.1,TLSv1.2,TLSv1.3 (使用 OpenSSL 1.1.1) TLSv1,TLSv1.1,TLSv1.2 (其他情况) Group Replication 支持 TLSv1.3

MySQL 8.0.26 和 MySQL 8.0.27

TLSv1,TLSv1.1,TLSv1.2,TLSv1.3 (使用 OpenSSL 1.1.1) TLSv1,TLSv1.1,TLSv1.2 (其他情况) TLSv1 和 TLSv1.1 已被弃用

MySQL 8.0.28 及以上版本

TLSv1.2,TLSv1.3

要在运行时确定 tls_version 的值,请使用以下语句:

代码语言:javascript复制
mysql> SHOW GLOBAL VARIABLES LIKE 'tls_version';
 --------------- ----------------------- 
| Variable_name | Value                 |
 --------------- ----------------------- 
| tls_version   | TLSv1.2,TLSv1.3       |
 --------------- ----------------------- 

要更改 tls_version 的值,请在服务器启动时设置。例如,要允许使用 TLSv1.2 或 TLSv1.3 协议的连接,但禁止使用较不安全的 TLSv1 和 TLSv1.1 协议的连接,请在服务器的 my.cnf 文件中使用以下行:

代码语言:javascript复制
[mysqld]
tls_version=TLSv1.2,TLSv1.3

要更加严格并仅允许 TLSv1.3 连接,设置 tls_version 如下:

代码语言:javascript复制
[mysqld]
tls_version=TLSv1.3

从 MySQL 8.0.16 开始,tls_version 可以在运行时更改。请参阅 Server-Side Runtime Configuration and Monitoring for Encrypted Connections。

在客户端,--tls-version 选项指定客户端程序允许连接到服务器的 TLS 协议版本。选项值的格式与之前描述的 tls_version 系统变量相同(一个或多个逗号分隔的协议版本列表)。

对于源/复制复制连接,其中此服务器实例是复制品,CHANGE REPLICATION SOURCE TO 语句(从 MySQL 8.0.23 开始)或 CHANGE MASTER TO 语句(MySQL 8.0.23 之前)的 SOURCE_TLS_VERSION | MASTER_TLS_VERSION 选项指定复制品允许连接到源的 TLS 协议版本。选项值的格式与之前描述的 tls_version 系统变量相同。参见 Section 19.3.1, “Setting Up Replication to Use Encrypted Connections”。

可以为SOURCE_TLS_VERSION | MASTER_TLS_VERSION指定的协议取决于 SSL 库。此选项独立于服务器tls_version值,并不受其影响。例如,作为副本的服务器可以配置tls_version设置为 TLSv1.3,以仅允许使用 TLSv1.3 的传入连接,但也可以配置SOURCE_TLS_VERSION | MASTER_TLS_VERSION设置为 TLSv1.2,以仅允许对源的传出副本连接使用 TLSv1.2。

对于 Group Replication 分布式恢复连接,其中此服务器实例是发起分布式恢复的加入成员(即客户端),group_replication_recovery_tls_version系统变量指定客户端允许的协议。同样,此选项独立于服务器tls_version值,并不受其影响,当此服务器实例是捐赠者时应用。Group Replication 服务器通常在其组成员身份的过程中既作为捐赠者又作为加入成员参与分布式恢复,因此应设置这两个系统变量。参见第 20.6.2 节,“使用安全套接字层(SSL)保护组通信连接”。

TLS 协议配置影响给定连接使用的协议,如连接 TLS 协议协商中所述。

允许的协议应该被选择,以免在列表中留下“漏洞”。例如,这些服务器配置数值没有漏洞:

代码语言:javascript复制
tls_version=TLSv1,TLSv1.1,TLSv1.2,TLSv1.3
tls_version=TLSv1.1,TLSv1.2,TLSv1.3
tls_version=TLSv1.2,TLSv1.3
tls_version=TLSv1.3

这些数值有漏洞,不应使用:

代码语言:javascript复制
tls_version=TLSv1,TLSv1.2       *(TLSv1.1 is missing)* tls_version=TLSv1.1,TLSv1.3     *(TLSv1.2 is missing)*

对于其他配置上下文,如客户端或副本,也适用于禁止漏洞。

除非你打算禁用加密连接,否则允许的协议列表不应为空。如果将 TLS 版本参数设置为空字符串,加密连接将无法建立:

  • tls_version:服务器不允许加密传入连接。
  • --tls-version:客户端不允许向服务器建立加密传出连接。
  • SOURCE_TLS_VERSION | MASTER_TLS_VERSION:副本不允许向源建立加密传出连接。
  • group_replication_recovery_tls_version:加入成员不允许与分布式恢复连接建立加密连接。
连接密码配置

一组默认的密码适用于加密连接,可以通过显式配置允许的密码来覆盖。在连接建立过程中,连接的双方必须允许一些共同的密码,否则连接将失败。在双��都允许的密码中,SSL 库选择由提供的具有最高优先级的证书支持的密码。

要指定适用于使用 TLS 协议直至 TLSv1.2 的加密连接的密码或密码:

  • 在服务器端设置ssl_cipher系统变量,并为客户端程序使用--ssl-cipher选项。
  • 对于常规的源/副本复制连接,在这个服务器实例作为源时,设置ssl_cipher系统变量。当这个服务器实例作为副本时,使用CHANGE REPLICATION SOURCE TO语句(从 MySQL 8.0.23 开始)或CHANGE MASTER TO语句(MySQL 8.0.23 之前)的SOURCE_SSL_CIPHER | MASTER_SSL_CIPHER选项。参见 Section 19.3.1, “Setting Up Replication to Use Encrypted Connections”。
  • 对于 Group Replication 组成员,对于 Group Replication 组通信连接以及 Group Replication 分布式恢复连接(其中这个服务器实例是捐赠者),设置ssl_cipher系统变量。对于 Group Replication 分布式恢复连接(其中这个服务器实例是加入成员),使用group_replication_recovery_ssl_cipher系统变量。参见 Section 20.6.2, “Securing Group Communication Connections with Secure Socket Layer (SSL)”")。

对于使用 TLSv1.3 的加密连接,OpenSSL 1.1.1 及更高版本支持以下密码套件,默认情况下启用前三个:

代码语言:javascript复制
TLS_AES_128_GCM_SHA256
TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
TLS_AES_128_CCM_SHA256

注意

在 MySQL 8.0.35 之前,TLS_AES_128_CCM_8_SHA256支持与服务器系统变量--tls-ciphersuites--admin-tls-ciphersuites一起使用。如果为 MySQL 8.0.35 及更高版本配置TLS_AES_128_CCM_8_SHA256,将生成一个弃用警告。

要显式配置允许的 TLSv1.3 密码套件,请设置以下参数。在每种情况下,配置值是一个零个或多个以冒号分隔的密码套件名称列表。

  • 在服务器端,使用tls_ciphersuites系统变量。如果未设置此变量,则其默认值为NULL,这意味着服务器允许默认一组密码套件。如果将变量设置为空字符串,则不启用任何密码套件,无法建立加密连接。
  • 在客户端端,使用--tls-ciphersuites选项。如果未设置此选项,则客户端允许默认一组密码套件。如果将选项设置为空字符串,则不启用任何密码套件,无法建立加密连接。
  • 对于常规的源/副本复制连接,在此服务器实例作为源时,请使用tls_ciphersuites系统变量。在此服务器实例作为副本时,请使用SOURCE_TLS_CIPHERSUITES | MASTER_TLS_CIPHERSUITES选项,用于CHANGE REPLICATION SOURCE TO语句(从 MySQL 8.0.23 开始)或CHANGE MASTER TO语句(在 MySQL 8.0.23 之前)。参见 Section 19.3.1, “Setting Up Replication to Use Encrypted Connections”。
  • 对于 Group Replication 组成员,在 Group Replication 组通信连接以及在此服务器实例作为捐赠者时的 Group Replication 分布式恢复连接中,请使用tls_ciphersuites系统变量。对于此服务器实例作为加入成员时的 Group Replication 分布式恢复连接,请使用group_replication_recovery_tls_ciphersuites系统变量。参见 Section 20.6.2, “Securing Group Communication Connections with Secure Socket Layer (SSL)”")。

注意

MySQL 8.0.16 版本开始支持密码套件,但要求 MySQL 服务器和客户端应用程序都使用 OpenSSL 1.1.1 或更高版本进行编译。

在 MySQL 8.0.16 至 8.0.18 中,group_replication_recovery_tls_ciphersuites系统变量和CHANGE REPLICATION SOURCE TO语句(从 MySQL 8.0.23 开始)或CHANGE MASTER TO语句(在 MySQL 8.0.23 之前)中的SOURCE_TLS_CIPHERSUITES | MASTER_TLS_CIPHERSUITES选项不可用。在这些版本中,如果用于源/副本复制连接的 TLSv1.3,或在分布式恢复的 Group Replication 中使用 TLSv1.3(从 MySQL 8.0.18 开始支持),则复制源或 Group Replication 捐赠服务器必须允许至少启用默认情况下启用的一个 TLSv1.3 密码套件。从 MySQL 8.0.19 开始,您可以使用选项配置客户端支持任何选择的密码套件,包括仅使用非默认密码套件(如果需要)。

给定密码可能仅适用于特定的 TLS 协议,这会影响 TLS 协议协商过程。请参阅连接 TLS 协议协商。

要确定给定服务器支持哪些密码,检查Ssl_cipher_list状态变量的会话值:

代码语言:javascript复制
SHOW SESSION STATUS LIKE 'Ssl_cipher_list';

Ssl_cipher_list状态变量列出了可能的 SSL 密码(非 SSL 连接为空)。如果 MySQL 支持 TLSv1.3,则该值包括可能的 TLSv1.3 密码套件。

注意

ECDSA 密码只能与使用 ECDSA 进行数字签名的 SSL 证书结合使用,并且不能与使用 RSA 的证书一起使用。MySQL 服务器的 SSL 证书自动生成过程不生成 ECDSA 签名证书,它只生成 RSA 签名证书。除非您有可用的 ECDSA 证书,请勿选择 ECDSA 密码。

对于使用 TLS.v1.3 的加密连接,MySQL 使用 SSL 库的默认密码套件列表。

对于使用 TLS 协议直至 TLSv1.2 的加密连接,MySQL 将以下默认密码列表传递给 SSL 库。

代码语言:javascript复制
ECDHE-ECDSA-AES128-GCM-SHA256
ECDHE-ECDSA-AES256-GCM-SHA384
ECDHE-RSA-AES128-GCM-SHA256
ECDHE-RSA-AES256-GCM-SHA384
ECDHE-ECDSA-CHACHA20-POLY1305
ECDHE-RSA-CHACHA20-POLY1305
ECDHE-ECDSA-AES256-CCM
ECDHE-ECDSA-AES128-CCM
DHE-RSA-AES128-GCM-SHA256
DHE-RSA-AES256-GCM-SHA384
DHE-RSA-AES256-CCM
DHE-RSA-AES128-CCM
DHE-RSA-CHACHA20-POLY1305

这些密码限制已经生效:

从 MySQL 8.0.35 开始,以下密码已被弃用,并在与服务器系统变量--ssl-cipher--admin-ssl-cipher一起使用时产生警告:

代码语言:javascript复制
ECDHE-ECDSA-AES128-SHA256
ECDHE-RSA-AES128-SHA256
ECDHE-ECDSA-AES256-SHA384
ECDHE-RSA-AES256-SHA384
DHE-DSS-AES128-GCM-SHA256
DHE-RSA-AES128-SHA256
DHE-DSS-AES128-SHA256
DHE-DSS-AES256-GCM-SHA384
DHE-RSA-AES256-SHA256
DHE-DSS-AES256-SHA256
ECDHE-RSA-AES128-SHA
ECDHE-ECDSA-AES128-SHA
ECDHE-RSA-AES256-SHA
ECDHE-ECDSA-AES256-SHA
DHE-DSS-AES128-SHA
DHE-RSA-AES128-SHA
TLS_DHE_DSS_WITH_AES_256_CBC_SHA
DHE-RSA-AES256-SHA
AES128-GCM-SHA256
DH-DSS-AES128-GCM-SHA256
ECDH-ECDSA-AES128-GCM-SHA256
AES256-GCM-SHA384
DH-DSS-AES256-GCM-SHA384
ECDH-ECDSA-AES256-GCM-SHA384
AES128-SHA256
DH-DSS-AES128-SHA256
ECDH-ECDSA-AES128-SHA256
AES256-SHA256
DH-DSS-AES256-SHA256
ECDH-ECDSA-AES256-SHA384
AES128-SHA
DH-DSS-AES128-SHA
ECDH-ECDSA-AES128-SHA
AES256-SHA
DH-DSS-AES256-SHA
ECDH-ECDSA-AES256-SHA
DH-RSA-AES128-GCM-SHA256
ECDH-RSA-AES128-GCM-SHA256
DH-RSA-AES256-GCM-SHA384
ECDH-RSA-AES256-GCM-SHA384
DH-RSA-AES128-SHA256
ECDH-RSA-AES128-SHA256
DH-RSA-AES256-SHA256
ECDH-RSA-AES256-SHA384
ECDHE-RSA-AES128-SHA
ECDHE-ECDSA-AES128-SHA
ECDHE-RSA-AES256-SHA
ECDHE-ECDSA-AES256-SHA
DHE-DSS-AES128-SHA
DHE-RSA-AES128-SHA
TLS_DHE_DSS_WITH_AES_256_CBC_SHA
DHE-RSA-AES256-SHA
AES128-SHA
DH-DSS-AES128-SHA
ECDH-ECDSA-AES128-SHA
AES256-SHA
DH-DSS-AES256-SHA
ECDH-ECDSA-AES256-SHA
DH-RSA-AES128-SHA
ECDH-RSA-AES128-SHA
DH-RSA-AES256-SHA
ECDH-RSA-AES256-SHA
DES-CBC3-SHA

以下密码已被永久限制:

代码语言:javascript复制
!DHE-DSS-DES-CBC3-SHA
!DHE-RSA-DES-CBC3-SHA
!ECDH-RSA-DES-CBC3-SHA
!ECDH-ECDSA-DES-CBC3-SHA
!ECDHE-RSA-DES-CBC3-SHA
!ECDHE-ECDSA-DES-CBC3-SHA

以下密码类别已被永久限制:

代码语言:javascript复制
!aNULL
!eNULL
!EXPORT
!LOW
!MD5
!DES
!RC2
!RC4
!PSK
!SSLv3

如果服务器启动时使用ssl_cert系统变量设置为使用任何前述受限密码或密码类别的证书,则服务器将以禁用加密连接的支持启动。

连接 TLS 协议协商

在 MySQL 中,连接尝试会协商双方都支持的最高 TLS 协议版本,该版本在双方都支持的协议兼容加密密码上可用。协商过程取决于诸如用于编译服务器和客户端的 SSL 库、TLS 协议和加密密码配置以及使用的密钥大小等因素:

要使连接尝试成功,服务器和客户端 TLS 协议配置必须允许一些共同的协议。

类似地,服务器和客户端加密密码配置必须允许一些共同的密码。给定的密码可能仅适用于特定的 TLS 协议,因此除非还有兼容的密码,否则在协商过程中不会选择协议。

如果 TLSv1.3 可用,则尽可能使用。 (这意味着服务器和客户端配置都必须允许 TLSv1.3,并且两者还必须允许一些 TLSv1.3 兼容的加密密码。)否则,MySQL 将继续使用可用协议列表,如果可能的话使用 TLSv1.2,依此类推。协商从更安全的协议到不太安全的协议进行。协商顺序与配置协议的顺序无关。例如,无论tls_version的值是TLSv1,TLSv1.1,TLSv1.2,TLSv1.3还是TLSv1.3,TLSv1.2,TLSv1.1,TLSv1,协商顺序都是相同的。

TLSv1.2 与所有密钥大小为 512 位或更小的密码不兼容。要使用此协议与此类密钥,请在服务器端设置ssl_cipher系统变量,或使用--ssl-cipher客户端选项显式指定密码名称:

代码语言:javascript复制
AES128-SHA
AES128-SHA256
AES256-SHA
AES256-SHA256
CAMELLIA128-SHA
CAMELLIA256-SHA
DES-CBC3-SHA
DHE-RSA-AES256-SHA
RC4-MD5
RC4-SHA
SEED-SHA

为了更好的安全性,请使用至少 2048 位的 RSA 密钥大小的证书。

如果服务器和客户端没有共同的允许协议,以及共同的协议兼容密码,服务器将终止连接请求。例如:

  • 如果服务器配置为tls_version=TLSv1.1,TLSv1.2
    • 对于使用--tls-version=TLSv1调用的客户端以及仅支持 TLSv1 的旧客户端,连接尝试将失败。
    • 类似地,为配置为MASTER_TLS_VERSION = 'TLSv1'的复制品以及仅支持 TLSv1 的旧复制品,连接尝试将失败。
  • 如果服务器配置为tls_version=TLSv1或是仅支持 TLSv1 的旧服务器:
    • 对于使用--tls-version=TLSv1.1,TLSv1.2调用的客户端,连接尝试将失败。
    • 同样,对于配置为MASTER_TLS_VERSION = 'TLSv1.1,TLSv1.2'的副本,连接尝试将失败。

MySQL 允许指定要支持的协议列表。此列表直接传递给底层 SSL 库,最终由该库决定实际启用来自提供的列表的哪些协议。有关 SSL 库处理此操作的信息,请参考 MySQL 源代码和 OpenSSL SSL_CTX_new() 文档。

监控当前客户端会话的 TLS 协议和密码

要确定当前客户端会话使用的加密 TLS 协议和密码,检查Ssl_versionSsl_cipher状态变量的会话值:

代码语言:javascript复制
mysql> SELECT * FROM performance_schema.session_status
       WHERE VARIABLE_NAME IN ('Ssl_version','Ssl_cipher');
 --------------- --------------------------- 
| VARIABLE_NAME | VARIABLE_VALUE            |
 --------------- --------------------------- 
| Ssl_cipher    | DHE-RSA-AES128-GCM-SHA256 |
| Ssl_version   | TLSv1.2                   |
 --------------- --------------------------- 

如果连接未加密,则两个变量的值为空。

8.3.3 创建 SSL 和 RSA 证书和密钥

原文:dev.mysql.com/doc/refman/8.0/en/creating-ssl-rsa-files.html

8.3.3.1 使用 MySQL 创建 SSL 和 RSA 证书和密钥

8.3.3.2 使用 openssl 创建 SSL 证书和密钥

8.3.3.3 使用 openssl 创建 RSA 密钥

以下讨论描述了如何在 MySQL 中创建 SSL 和 RSA 支持所需的文件。文件的创建可以使用 MySQL 自身提供的工具,也可以直接调用 openssl 命令来执行。

SSL 证书和密钥文件使 MySQL 能够支持使用 SSL 进行加密连接。参见 第 8.3.1 节,“配置 MySQL 使用加密连接”。

RSA 密钥文件使 MySQL 能够支持通过 sha256_passwordcaching_sha2_password 插件对由未加密连接进行身份验证的帐户进行安全密码交换。参见 第 8.4.1.3 节,“SHA-256 可插拔认证”,以及 第 8.4.1.2 节,“缓存 SHA-2 可插拔认证”。

原文:dev.mysql.com/doc/refman/8.0/en/creating-ssl-rsa-files-using-mysql.html

8.3.3.1 使用 MySQL 创建 SSL 和 RSA 证书和密钥

MySQL 提供了以下方法来创建 SSL 证书和密钥文件以及 RSA 密钥对文件,以支持使用 SSL 进行加密连接和在未加密连接上使用 RSA 进行安全密码交换,如果这些文件丢失:

  • 服务器可以在启动时自动生成这些文件,适用于 MySQL 发行版。
  • 用户可以手动调用mysql_ssl_rsa_setup实用程序(自 MySQL 8.0.34 起已弃用)。
  • 对于某些发行类型,如 RPM 和 DEB 软件包,mysql_ssl_rsa_setup在数据目录初始化期间调用。在这种情况下,只要openssl命令可用,MySQL 发行版不必使用 OpenSSL 进行编译。

重要

服务器自动生成和mysql_ssl_rsa_setup有助于降低使用 SSL 的门槛,使生成所需文件变得更容易。然而,通过这些方法生成的证书是自签名的,可能不太安全。在您获得使用这些文件的经验后,考虑从注册的证书颁发机构获取证书/密钥材料。

重要

如果连接到 MySQL 服务器实例的客户端使用带有extendedKeyUsage扩展(X.509 v3 扩展)的 SSL 证书,则扩展密钥用途必须包括客户端认证(clientAuth)。如果 SSL 证书仅指定用于服务器认证(serverAuth)和其他非客户端证书目的,证书验证将失败,客户端连接到 MySQL 服务器实例将失败。MySQL 服务器生成的 SSL 证书中没有extendedKeyUsage扩展。如果您使用另一种方式创建的自己的客户端证书,请确保任何extendedKeyUsage扩展包括客户端认证。

  • 自动 SSL 和 RSA 文件生成
  • 使用 mysql_ssl_rsa_setup 手动生成 SSL 和 RSA 文件
  • SSL 和 RSA 文件特性
自动 SSL 和 RSA 文件生成

对于使用 OpenSSL 编译的 MySQL 发行版,MySQL 服务器具有在启动时自动生成缺失的 SSL 和 RSA 文件的能力。auto_generate_certssha256_password_auto_generate_rsa_keyscaching_sha2_password_auto_generate_rsa_keys系统变量控制这些文件的自动生成。这些变量默认启用。它们可以在启动时启用和检查,但不能在运行时设置。

在启动时,如果启用了auto_generate_certs系统变量,没有指定除--ssl之外的其他 SSL 选项,并且数据目录中缺少服务器端 SSL 文件,则服务器会自动在数据目录中生成服务器端和客户端 SSL 证书和密钥文件。这些文件使得可以使用 SSL 加密客户端连接;参见第 8.3.1 节,“配置 MySQL 使用加密连接”。

服务器检查数据目录中具有以下名称的 SSL 文件:

代码语言:javascript复制
ca.pem
server-cert.pem
server-key.pem

如果存在任何这些文件,则服务器不会创建 SSL 文件。否则,它会创建它们,以及一些额外的文件:

代码语言:javascript复制
ca.pem               Self-signed CA certificate
ca-key.pem           CA private key
server-cert.pem      Server certificate
server-key.pem       Server private key
client-cert.pem      Client certificate
client-key.pem       Client private key

如果服务器自动生成 SSL 文件,则使用ca.pemserver-cert.pemserver-key.pem文件的名称来设置相应的系统变量(ssl_cassl_certssl_key)。

在启动时,如果满足以下所有条件,则服务器会自动在数据目录中生成 RSA 私钥/公钥对文件:启用了sha256_password_auto_generate_rsa_keyscaching_sha2_password_auto_generate_rsa_keys系统变量;未指定 RSA 选项;数据目录中缺少 RSA 文件。这些密钥对文件使得可以在通过sha256_passwordcaching_sha2_password插件进行身份验证的帐户之间使用 RSA 在未加密连接上进行安全密码交换;参见第 8.4.1.3 节,“SHA-256 可插拔认证”和第 8.4.1.2 节,“缓存 SHA-2 可插拔认证”。

服务器检查数据目录中具有以下名称的 RSA 文件:

代码语言:javascript复制
private_key.pem      Private member of private/public key pair
public_key.pem       Public member of private/public key pair

如果存在任何这些文件,则服务器不会创建 RSA 文件。否则,它会创建它们。

如果服务器自动生成 RSA 文件,则使用它们的名称来设置相应的系统变量(sha256_password_private_key_pathsha256_password_public_key_path; caching_sha2_password_private_key_pathcaching_sha2_password_public_key_path)。

使用 mysql_ssl_rsa_setup 手动生成 SSL 和 RSA 文件

MySQL 发行版包含一个mysql_ssl_rsa_setup实用程序(自 MySQL 8.0.34 起已弃用),可以手动调用以生成 SSL 和 RSA 文件。该实用程序包含在所有 MySQL 发行版中,但需要openssl命令可用。有关使用说明,请参见第 6.4.3 节,“mysql_ssl_rsa_setup — Create SSL/RSA Files”。

SSL 和 RSA 文件特征

服务器自动创建的 SSL 和 RSA 文件或通过调用mysql_ssl_rsa_setup创建的文件具有以下特征:

SSL 和 RSA 的位数为 2048 位。

SSL CA 证书是自签名的。

SSL 服务器和客户端证书使用 CA 证书和密钥签名,使用sha256WithRSAEncryption签名算法。

SSL 证书使用这些通用名称(CN)值,具有适当的证书类型(CA、服务器、客户端):

代码语言:javascript复制
ca.pem:         MySQL_Server_*suffix*_Auto_Generated_CA_Certificate
server-cert.pm: MySQL_Server_*suffix*_Auto_Generated_Server_Certificate
client-cert.pm: MySQL_Server_*suffix*_Auto_Generated_Client_Certificate

*suffix*值基于 MySQL 版本号。对于由mysql_ssl_rsa_setup生成的文件,可以使用--suffix选项显式指定后缀。

对于服务器生成的文件,如果结果 CN 值超过 64 个字符,则名称的_*后缀部分将被省略。

SSL 文件的国家(C)、州或省(ST)、组织(O)、组织单位名称(OU)和电子邮件地址为空值。

由服务器或mysql_ssl_rsa_setup生成的 SSL 文件从生成时起有效期为十年。

RSA 文件不会过期。

SSL 文件对于每个证书/密钥对具有不同的序列号(CA 为 1,服务器为 2,客户端为 3)。

服务器自动创建的文件归属于运行服务器的账户。使用 mysql_ssl_rsa_setup 创建的文件归属于调用该程序的用户。在支持 chown() 系统调用的系统上,如果程序由 root 调用并且提供了 --uid 选项来指定应该拥有这些文件的用户,则可以更改这一点。

在 Unix 和类 Unix 系统上,证书文件的文件访问模式为 644(即,全局可读),密钥文件的文件访问模式为 600(即,只能由运行服务器的账户访问)。

要查看 SSL 证书的内容(例如,检查其有效日期范围),可以直接调用 openssl

代码语言:javascript复制
openssl x509 -text -in ca.pem
openssl x509 -text -in server-cert.pem
openssl x509 -text -in client-cert.pem

使用以下 SQL 语句也可以检查 SSL 证书的过期信息:

代码语言:javascript复制
mysql> SHOW STATUS LIKE 'Ssl_server_not%';
 ----------------------- -------------------------- 
| Variable_name         | Value                    |
 ----------------------- -------------------------- 
| Ssl_server_not_after  | Apr 28 14:16:39 2027 GMT |
| Ssl_server_not_before | May  1 14:16:39 2017 GMT |
 ----------------------- -------------------------- 

原文:dev.mysql.com/doc/refman/8.0/en/creating-ssl-files-using-openssl.html

8.3.3.2 使用 openssl 创建 SSL 证书和密钥

本节描述了如何使用openssl命令设置供 MySQL 服务器和客户端使用的 SSL 证书和密钥文件。第一个示例显示了一个简化的过程,类似于您可能从命令行中使用的过程。第二个示例显示了一个包含更多细节的脚本。前两个示例适用于 Unix,并且都使用 OpenSSL 的一部分的openssl命令。第三个示例描述了如何在 Windows 上设置 SSL 文件。

注意

有比本文所述过程更简单的生成 SSL 所需文件的替代方法:让服务器自动生成它们或使用mysql_ssl_rsa_setup程序(自 8.0.34 起已弃用)。请参阅第 8.3.3.1 节,“使用 MySQL 创建 SSL 和 RSA 证书和密钥”。

重要

无论您使用何种方法生成证书和密钥文件,用于服务器和客户端证书/密钥的通用名称值必须与用于 CA 证书的通用名称值不同。否则,使用 OpenSSL 编译的服务器的证书和密钥文件将无法工作。在这种情况下的典型错误是:

代码语言:javascript复制
ERROR 2026 (HY000): SSL connection error:
error:00000001:lib(0):func(0):reason(1)

重要

如果连接到 MySQL 服务器实例的客户端使用带有extendedKeyUsage扩展(X.509 v3 扩展)的 SSL 证书,则扩展密钥用途必须包括客户端认证(clientAuth)。如果 SSL 证书仅指定用于服务器认证(serverAuth)和其他非客户端证书目的,证书验证将失败,客户端连接到 MySQL 服务器实例将失败。在本主题中按照说明使用openssl命令创建的 SSL 证书中没有extendedKeyUsage扩展。如果您使用其他方式创建的自己的客户端证书,请确保任何extendedKeyUsage扩展包括客户端认证。

  • 示例 1:在 Unix 命令行上创建 SSL 文件
  • 示例 2:使用 Unix 脚本创建 SSL 文件
  • 示例 3:在 Windows 上创建 SSL 文件
示例 1:在 Unix 命令行上创建 SSL 文件

以下示例显示了一组命令,用于创建 MySQL 服务器和客户端证书和密钥文件。您必须通过openssl命令回答几个提示。要生成测试文件,可以对所有提示按 Enter 键。要生成用于生产的文件,应提供非空响应。

代码语言:javascript复制
# Create clean environment
rm -rf newcerts
mkdir newcerts && cd newcerts

# Create CA certificate
openssl genrsa 2048 > ca-key.pem
openssl req -new -x509 -nodes -days 3600 
        -key ca-key.pem -out ca.pem

# Create server certificate, remove passphrase, and sign it
# server-cert.pem = public key, server-key.pem = private key
openssl req -newkey rsa:2048 -days 3600 
        -nodes -keyout server-key.pem -out server-req.pem
openssl rsa -in server-key.pem -out server-key.pem
openssl x509 -req -in server-req.pem -days 3600 
        -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem

# Create client certificate, remove passphrase, and sign it
# client-cert.pem = public key, client-key.pem = private key
openssl req -newkey rsa:2048 -days 3600 
        -nodes -keyout client-key.pem -out client-req.pem
openssl rsa -in client-key.pem -out client-key.pem
openssl x509 -req -in client-req.pem -days 3600 
        -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem

生成证书后,请验证它们:

代码语言:javascript复制
openssl verify -CAfile ca.pem server-cert.pem client-cert.pem

你应该看到如下响应:

代码语言:javascript复制
server-cert.pem: OK
client-cert.pem: OK

要查看证书的内容(例如,检查证书有效日期范围),可以像这样调用openssl

代码语言:javascript复制
openssl x509 -text -in ca.pem
openssl x509 -text -in server-cert.pem
openssl x509 -text -in client-cert.pem

现在你有一组文件,可以按以下方式使用:

  • ca.pem:用于在服务器端设置ssl_ca系统变量和客户端端的--ssl-ca选项。(如果使用 CA 证书,则两端必须相同。)
  • server-cert.pemserver-key.pem:用于在服务器端设置ssl_certssl_key系统变量。
  • client-cert.pemclient-key.pem:将这些用作客户端端的--ssl-cert--ssl-key选项的参数。

对于额外的使用说明,请参见第 8.3.1 节,“配置 MySQL 使用加密连接”。

示例 2:在 Unix 上使用脚本创建 SSL 文件

这是一个示例脚本,展示如何为 MySQL 设置 SSL 证书和密钥文件。执行脚本后,按照第 8.3.1 节,“配置 MySQL 使用加密连接”中描述的方式用于 SSL 连接。

代码语言:javascript复制
DIR=`pwd`/openssl
PRIV=$DIR/private

mkdir $DIR $PRIV $DIR/newcerts
cp /usr/share/ssl/openssl.cnf $DIR
replace ./demoCA $DIR -- $DIR/openssl.cnf

# Create necessary files: $database, $serial and $new_certs_dir
# directory (optional)

touch $DIR/index.txt
echo "01" > $DIR/serial

#
# Generation of Certificate Authority(CA)
#

openssl req -new -x509 -keyout $PRIV/cakey.pem -out $DIR/ca.pem 
    -days 3600 -config $DIR/openssl.cnf

# Sample output:
# Using configuration from /home/jones/openssl/openssl.cnf
# Generating a 1024 bit RSA private key
# ................      
# .........      
# writing new private key to '/home/jones/openssl/private/cakey.pem'
# Enter PEM pass phrase:
# Verifying password - Enter PEM pass phrase:
# -----
# You are about to be asked to enter information to be
# incorporated into your certificate request.
# What you are about to enter is what is called a Distinguished Name
# or a DN.
# There are quite a few fields but you can leave some blank
# For some fields there will be a default value,
# If you enter '.', the field will be left blank.
# -----
# Country Name (2 letter code) [AU]:FI
# State or Province Name (full name) [Some-State]:.
# Locality Name (eg, city) []:
# Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB
# Organizational Unit Name (eg, section) []:
# Common Name (eg, YOUR name) []:MySQL admin
# Email Address []:

#
# Create server request and key
#
openssl req -new -keyout $DIR/server-key.pem -out 
    $DIR/server-req.pem -days 3600 -config $DIR/openssl.cnf

# Sample output:
# Using configuration from /home/jones/openssl/openssl.cnf
# Generating a 1024 bit RSA private key
# ..      
# ..........      
# writing new private key to '/home/jones/openssl/server-key.pem'
# Enter PEM pass phrase:
# Verifying password - Enter PEM pass phrase:
# -----
# You are about to be asked to enter information that will be
# incorporated into your certificate request.
# What you are about to enter is what is called a Distinguished Name
# or a DN.
# There are quite a few fields but you can leave some blank
# For some fields there will be a default value,
# If you enter '.', the field will be left blank.
# -----
# Country Name (2 letter code) [AU]:FI
# State or Province Name (full name) [Some-State]:.
# Locality Name (eg, city) []:
# Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB
# Organizational Unit Name (eg, section) []:
# Common Name (eg, YOUR name) []:MySQL server
# Email Address []:
#
# Please enter the following 'extra' attributes
# to be sent with your certificate request
# A challenge password []:
# An optional company name []:

#
# Remove the passphrase from the key
#
openssl rsa -in $DIR/server-key.pem -out $DIR/server-key.pem

#
# Sign server cert
#
openssl ca -cert $DIR/ca.pem -policy policy_anything 
    -out $DIR/server-cert.pem -config $DIR/openssl.cnf 
    -infiles $DIR/server-req.pem

# Sample output:
# Using configuration from /home/jones/openssl/openssl.cnf
# Enter PEM pass phrase:
# Check that the request matches the signature
# Signature ok
# The Subjects Distinguished Name is as follows
# countryName           :PRINTABLE:'FI'
# organizationName      :PRINTABLE:'MySQL AB'
# commonName            :PRINTABLE:'MySQL admin'
# Certificate is to be certified until Sep 13 14:22:46 2003 GMT
# (365 days)
# Sign the certificate? [y/n]:y
#
#
# 1 out of 1 certificate requests certified, commit? [y/n]y
# Write out database with 1 new entries
# Data Base Updated

#
# Create client request and key
#
openssl req -new -keyout $DIR/client-key.pem -out 
    $DIR/client-req.pem -days 3600 -config $DIR/openssl.cnf

# Sample output:
# Using configuration from /home/jones/openssl/openssl.cnf
# Generating a 1024 bit RSA private key
# .....................................      
# .............................................      
# writing new private key to '/home/jones/openssl/client-key.pem'
# Enter PEM pass phrase:
# Verifying password - Enter PEM pass phrase:
# -----
# You are about to be asked to enter information that will be
# incorporated into your certificate request.
# What you are about to enter is what is called a Distinguished Name
# or a DN.
# There are quite a few fields but you can leave some blank
# For some fields there will be a default value,
# If you enter '.', the field will be left blank.
# -----
# Country Name (2 letter code) [AU]:FI
# State or Province Name (full name) [Some-State]:.
# Locality Name (eg, city) []:
# Organization Name (eg, company) [Internet Widgits Pty Ltd]:MySQL AB
# Organizational Unit Name (eg, section) []:
# Common Name (eg, YOUR name) []:MySQL user
# Email Address []:
#
# Please enter the following 'extra' attributes
# to be sent with your certificate request
# A challenge password []:
# An optional company name []:

#
# Remove the passphrase from the key
#
openssl rsa -in $DIR/client-key.pem -out $DIR/client-key.pem

#
# Sign client cert
#

openssl ca -cert $DIR/ca.pem -policy policy_anything 
    -out $DIR/client-cert.pem -config $DIR/openssl.cnf 
    -infiles $DIR/client-req.pem

# Sample output:
# Using configuration from /home/jones/openssl/openssl.cnf
# Enter PEM pass phrase:
# Check that the request matches the signature
# Signature ok
# The Subjects Distinguished Name is as follows
# countryName           :PRINTABLE:'FI'
# organizationName      :PRINTABLE:'MySQL AB'
# commonName            :PRINTABLE:'MySQL user'
# Certificate is to be certified until Sep 13 16:45:17 2003 GMT
# (365 days)
# Sign the certificate? [y/n]:y
#
#
# 1 out of 1 certificate requests certified, commit? [y/n]y
# Write out database with 1 new entries
# Data Base Updated

#
# Create a my.cnf file that you can use to test the certificates
#

cat <<EOF > $DIR/my.cnf
[client]
ssl-ca=$DIR/ca.pem
ssl-cert=$DIR/client-cert.pem
ssl-key=$DIR/client-key.pem
[mysqld]
ssl_ca=$DIR/ca.pem
ssl_cert=$DIR/server-cert.pem
ssl_key=$DIR/server-key.pem
EOF
示例 3:在 Windows 上创建 SSL 文件

如果您的系统尚未安装 OpenSSL,请下载 Windows 版。可在此处查看可用软件包的概述:

代码语言:javascript复制
http://www.slproweb.com/products/Win32OpenSSL.html

根据您的架构(32 位或 64 位)选择 Win32 OpenSSL Light 或 Win64 OpenSSL Light 软件包。默认安装位置为C:OpenSSL-Win32C:OpenSSL-Win64,取决于您下载的软件包。以下说明假定默认位置为C:OpenSSL-Win32。如果您使用 64 位软件包,则根据需要进行修改。

如果在安装过程中出现消息指示“…关键组件丢失:Microsoft Visual C 2019 Redistributables”,请取消安装并根据您的架构(32 位或 64 位)再次下载以下软件包之一:

Visual C 2008 Redistributables(x86),可在以下位置找到:

代码语言:javascript复制
http://www.microsoft.com/downloads/details.aspx?familyid=9B2DA534-3E03-4391-8A4D-074B9F2BC1BF

Visual C 2008 Redistributables(x64),可在以下位置找到:

代码语言:javascript复制
http://www.microsoft.com/downloads/details.aspx?familyid=bd2a6171-e2d6-4230-b809-9a8d7548c1b6

安装额外的软件包后,重新启动 OpenSSL 设置过程。

在安装过程中,将默认的C:OpenSSL-Win32作为安装路径,并保持默认选项'将 OpenSSL DLL 文件复制到 Windows 系统目录'被选中。

安装完成后,将C:OpenSSL-Win32bin添加到服务器的 Windows 系统路径变量中(根据您的 Windows 版本,以下路径设置说明可能略有不同):

在 Windows 桌面上,右键单击“我的电脑”图标,然后选择“属性”。

从出现的系统属性菜单中选择“高级”选项卡,然后点击“环境变量”按钮。

在系统变量下,选择“Path”,然后点击“编辑”按钮。应该会出现“编辑系统变量”对话框。

在末尾添加';C:OpenSSL-Win32bin'(注意分号)。

依次按下 3 次“确定”按钮。

通过打开一个新的命令控制台(开始>运行>cmd.exe)并验证 OpenSSL 是否可用来检查 OpenSSL 是否已正确集成到 Path 变量中:

代码语言:javascript复制
Microsoft Windows [Version ...]
Copyright (c) 2006 Microsoft Corporation. All rights reserved.

C:Windowssystem32>cd 

C:>openssl
OpenSSL> exit <<< If you see the OpenSSL prompt, installation was successful.

C:>

安装 OpenSSL 后,使用类似于本节前面示例 1 的指令,但需进行以下更改:

更改以下 Unix 命令:

代码语言:javascript复制
# Create clean environment
rm -rf newcerts
mkdir newcerts && cd newcerts

在 Windows 上,使用以下命令代替:

代码语言:javascript复制
# Create clean environment
md c:newcerts
cd c:newcerts

当命令行末尾显示一个''字符时,必须删除此''字符,并将命令行输入在同一行上。

生成证书和密钥文件后,要将它们用于 SSL 连接,请参阅第 8.3.1 节,“配置 MySQL 使用加密连接”。

原文:dev.mysql.com/doc/refman/8.0/en/creating-rsa-files-using-openssl.html

8.3.3.3 使用 openssl 创建 RSA 密钥

本节描述如何使用openssl命令设置 RSA 密钥文件,使 MySQL 能够支持通过未加密连接进行安全密码交换的帐户,这些帐户由sha256_passwordcaching_sha2_password插件进行身份验证。

注意

有比本文所述过程更简单的生成 RSA 所需文件的替代方法:让服务器自动生成它们或使用mysql_ssl_rsa_setup程序(自 MySQL 8.0.34 起已弃用)。请参阅 Section 8.3.3.1, “使用 MySQL 创建 SSL 和 RSA 证书和密钥”。

要创建 RSA 私钥和公钥文件,请在登录用于运行 MySQL 服务器的系统帐户时运行以下命令,以便这些文件归该帐户所有:

代码语言:javascript复制
openssl genrsa -out private_key.pem 2048
openssl rsa -in private_key.pem -pubout -out public_key.pem

这些命令创建了 2,048 位的密钥。要创建更强大的密钥,请使用更大的值。

然后设置密钥文件的访问模式。私钥应仅由服务器可读,而公钥可以自由分发给客户端用户:

代码语言:javascript复制
chmod 400 private_key.pem
chmod 444 public_key.pem

8.3.4 通过 SSH 从 Windows 远程连接到 MySQL

原文:dev.mysql.com/doc/refman/8.0/en/windows-and-ssh.html

本节描述了如何通过 SSH 与远程 MySQL 服务器建立加密连接。这些信息由 David Carlson 提供 <dcarlson@mplcomm.com>

  1. 在您的 Windows 机器上安装一个 SSH 客户端。有关 SSH 客户端的比较,请参见en.wikipedia.org/wiki/Comparison_of_SSH_clients
  2. 启动您的 Windows SSH 客户端。将Host_Name = *yourmysqlserver_URL_or_IP*设置为您的 MySQL 服务器的 URL 或 IP。将userid=*your_userid*设置为登录到服务器的用户 ID。这个userid值可能与您的 MySQL 账户的用户名不同。
  3. 设置端口转发。可以进行远程转发(设置local_port: 3306remote_host: *yourmysqlservername_or_ip*remote_port: 3306)或本地转发(设置port: 3306host: localhostremote port: 3306)。
  4. 保存所有设置,否则下次必须重新设置。
  5. 使用您刚刚创建的 SSH 会话登录到服务器。
  6. 在您的 Windows 机器上,启动一些 ODBC 应用程序(如 Access)。
  7. 在 Windows 中创建一个新文件,并以与通常相同的方式链接到 MySQL,只是在 MySQL 主机服务器处键入localhost,而不是*yourmysqlservername*。

此时,您应该已经建立了使用 SSH 加密的 MySQL 的 ODBC 连接。

8.3.5 重用 SSL 会话

原文:dev.mysql.com/doc/refman/8.0/en/reusing-ssl-sessions.html

截至 MySQL 8.0.29,MySQL 客户端程序可以选择恢复先前的 SSL 会话,前提是服务器在其运行时缓存中具有该会话。本节描述了有利于 SSL 会话重用的条件,用于管理和监控会话缓存的服务器变量,以及用于存储和重用会话数据的客户端命令行选项。

  • 用于 SSL 会话重用的服务器端运行时配置和监控
  • 用于 SSL 会话重用的客户端端配置

每次完整的 TLS 交换在计算和网络开销方面都可能很昂贵,如果使用 TLSv1.3 则开销较小。通过从已建立的会话中提取会话票证,然后在建立下一个连接时提交该票证,如果会话可以被重用,则总体成本会降低。例如,考虑具有可以打开多个连接并生成更快速度的网页的好处。

通常,在 SSL 会话可以被重用之前,必须满足以下条件:

  • 服务器必须将其会话缓存保留在内存中。
  • 服务器端会话缓存超时时间不能已过期。
  • 每个客户端都必须维护一个活动会话的缓存并保持其安全。

C 应用程序可以利用 C API 功能来启用加密连接的会话重用(参见 SSL 会话重用)。

用于 SSL 会话重用的服务器端运行时配置和监控

为了创建初始的 TLS 上下文,服务器使用启动时上下文相关系统变量的值。为了暴露上下文值,服务器还初始化了一组相应的状态变量。以下表格显示了定义服务器运行时会话缓存的系统变量以及暴露当前活动会话缓存值的相应状态变量。

表 8.15 用于会话重用的系统和状态变量

系统变量名

对应的状态变量名

ssl_session_cache_mode

Ssl_session_cache_mode

ssl_session_cache_timeout

Ssl_session_cache_timeout

注意

ssl_session_cache_mode服务器变量的值为ON时,这是默认模式,Ssl_session_cache_mode状态变量的值为SERVER

SSL 会话缓存变量适用于mysql_mainmysql_admin TLS 通道。它们的值也作为性能模式tls_channel_status表中的属性公开,以及任何其他活动 TLS 上下文的属性。

要在运行时重新配置 SSL 会话缓存,请使用以下步骤:

将应更改为其新值的每个与缓存相关的系统变量设置为其新值。例如,将缓存超时值从默认值(300 秒)更改为 600 秒:

代码语言:javascript复制
mysql> SET GLOBAL ssl_session_cache_timeout = 600;

每对系统和状态变量的成员可能由于重新配置过程的方式而暂时具有不同的值。

代码语言:javascript复制
mysql> SHOW VARIABLES LIKE 'ssl_session_cache_timeout';
 --------------------------- ------- 
| Variable_name             | Value |
 --------------------------- ------- 
| ssl_session_cache_timeout | 600   |
 --------------------------- ------- 
1 row in set (0.00 sec)

mysql> SHOW STATUS LIKE 'Ssl_session_cache_timeout';
 --------------------------- ------- 
| Variable_name             | Value |
 --------------------------- ------- 
| Ssl_session_cache_timeout | 300   |
 --------------------------- ------- 
1 row in set (0.00 sec)

有关设置变量值的其他信息,请参阅系统变量赋值。

执行ALTER INSTANCE RELOAD TLS。此语句会根据缓存相关系统变量的当前值重新配置活动的 TLS 上下文。它还会将缓存相关状态变量设置为反映新活动缓存值。该语句需要CONNECTION_ADMIN权限。

代码语言:javascript复制
mysql> ALTER INSTANCE RELOAD TLS;
Query OK, 0 rows affected (0.01 sec)

mysql> SHOW VARIABLES LIKE 'ssl_session_cache_timeout';
 --------------------------- ------- 
| Variable_name             | Value |
 --------------------------- ------- 
| ssl_session_cache_timeout | 600   |
 --------------------------- ------- 
1 row in set (0.00 sec)

mysql> SHOW STATUS LIKE 'Ssl_session_cache_timeout';
 --------------------------- ------- 
| Variable_name             | Value |
 --------------------------- ------- 
| Ssl_session_cache_timeout | 600   |
 --------------------------- ------- 
1 row in set (0.00 sec)

在执行ALTER INSTANCE RELOAD TLS后建立的新连接使用新的 TLS 上下文。现有连接不受影响。

SSL 会话重用的客户端端配置

所有 MySQL 客户端程序都能够重用先前会话,用于与同一服务器建立的新加密连接,前提是您在原始连接仍处于活动状态时存储了会话数据。会话数据存储到文件中,当您再次调用客户端时,���会指定此文件。

要存储和重用 SSL 会话数据,请使用以下步骤:

调用mysql以建立到运行 MySQL 8.0.29 或更高版本的服务器的加密连接。

使用ssl_session_data_print命令指定一个文件路径,您可以在其中安全地存储当前活动会话数据。例如:

代码语言:javascript复制
mysql> ssl_session_data_print ~/private-dir/session.txt

会话数据以以空终止的、PEM 编码的 ANSI 字符串形式获取。如果省略路径和文件名,则该字符串将打印到标准输出。

从命令解释器的提示符中,调用任何 MySQL 客户端程序以建立到同一服务器的新加密连接。要重用会话数据,请指定--ssl-session-data命令行选项和文件参数。

例如,使用mysql建立一个新连接:

代码语言:javascript复制
mysql -u admin -p --ssl-session-data=~/private-dir/session.txt

然后使用mysqlshow客户端:

代码语言:javascript复制
mysqlshow -u admin -p --ssl-session-data=~/private-dir/session.txt
Enter password: *****
 -------------------- 
|     Databases      |
 -------------------- 
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| world              |
 -------------------- 

在每个示例中,客户端尝试恢复原始会话,同时与同一服务器建立新连接。

要确认mysql是否重用了会话,请查看status命令的输出。如果当前活动的mysql连接确实恢复了会话,则状态信息包括SSL 会话重用: true

除了mysqlmysqlshow外,SSL 会话重用也适用于mysqladminmysqlbinlogmysqlcheckmysqldumpmysqlimportmysqlpumpmysqlslapmysqltestmysql_migrate_keyringmysql_secure_installationmysql_upgrade

几种情况可能会阻止成功检索会话数据。例如,如果会话未完全连接、不是 SSL 会话、服务器尚未发送会话数据或 SSL 会话无法重用。即使有正确存储的会话数据,服务器的会话缓存也可能超时。无论原因是什么,如果指定了--ssl-session-data,但会话无法重用,则默认情况下会返回错误。例如:

代码语言:javascript复制
mysqlshow -u admin -p --ssl-session-data=~/private-dir/session.txt
Enter password: *****
ERROR:
--ssl-session-data specified but the session was not reused.

为了抑制错误消息,并通过在命令行上静默创建一个新会话来建立连接,需要指定--ssl-session-data-continue-on-failed-reuse,以及--ssl-session-data。如果服务器的缓存超时已过期,可以将会话数据再次存储到同一文件中。默认服务器缓存超时可以延长(参见 SSL 会话重用的服务器端运行时配置和监控)。

8.4 安全组件和插件

原文:dev.mysql.com/doc/refman/8.0/en/security-plugins.html

8.4.1 认证插件

8.4.2 连接控制插件

8.4.3 密码验证组件

8.4.4 MySQL 密钥环

8.4.5 MySQL 企业审计

8.4.6 审计消息组件

8.4.7 MySQL 企业防火墙

MySQL 包括几个实现安全功能的组件和插件:

  • 用于验证客户端连接到 MySQL 服务器的插件。有几种认证协议的插件可用。有关认证过程的一般讨论,请参见 第 8.2.17 节,“可插拔认证”。有关特定认证插件的特性,请参见 第 8.4.1 节,“认证插件”。
  • 用于实施密码强度策略和评估潜在密码强度的密码验证组件。参见 第 8.4.3 节,“密码验证组件”。
  • 提供安全存储敏感信息的密钥环插件。参见 第 8.4.4 节,“MySQL 密钥环”。
  • (仅适用于 MySQL 企业版)MySQL 企业审计,使用服务器插件实现,使用开放的 MySQL 审计 API,可以对在特定 MySQL 服务器上执行的连接和查询活动进行标准、基于策略的监视和记录。设计符合 Oracle 审计规范,MySQL 企业审计为受内部和外部监管指导的应用程序提供了一个开箱即用、易于使用的审计和合规解决方案。参见 第 8.4.5 节,“MySQL 企业审计”。
  • 一个函数使应用程序能够将自己的消息事件添加到审计日志中。参见 第 8.4.6 节,“审计消息组件”。
  • (仅适用于 MySQL 企业版)MySQL 企业防火墙,一种应用级防火墙,使数据库管理员能够根据匹配接受的语句模式列表来允许或拒绝 SQL 语句执行。这有助于加固 MySQL 服务器,防止 SQL 注入等攻击或利用应用程序以其合法查询工作负载特征之外的方式。参见 第 8.4.7 节,“MySQL 企业防火墙”。
  • (仅适用于 MySQL 企业版) MySQL 企业数据脱敏和去标识化,实现为一个包含插件和一组函数的插件库。数据脱敏通过用替代值替换真实值来隐藏敏感信息。MySQL 企业数据脱敏和去标识化函数可以使用多种方法对现有数据进行脱敏,例如混淆(删除识别特征)、生成格式化的随机数据以及数据替换或替代。请参阅第 8.5 节,“MySQL 企业数据脱敏和去标识化”。

- 8.4.1 认证插件

原文:dev.mysql.com/doc/refman/8.0/en/authentication-plugins.html

8.4.1.1 本地可插拔认证

8.4.1.2 缓存 SHA-2 可插拔认证

8.4.1.3 SHA-256 可插拔认证

8.4.1.4 客户端明文可插拔认证

8.4.1.5 PAM 可插拔认证

8.4.1.6 Windows 可插拔认证

8.4.1.7 LDAP 可插拔认证

8.4.1.8 Kerberos 可插拔认证

8.4.1.9 无登录可插拔认证

8.4.1.10 套接字对等凭证可插拔认证

8.4.1.11 FIDO 可插拔认证

8.4.1.12 测试可插拔认证

8.4.1.13 可插拔认证系统变量

注意

如果您正在寻找关于authentication_oci插件的信息,这仅适用于 MySQL HeatWave 服务。请参阅authentication_oci 插件,在MySQL HeatWave Service手册中。

以下各节描述了 MySQL 中可用的可插拔认证方法以及实现这些方法的插件。有关认证过程的一般讨论,请参阅第 8.2.17 节,“可插拔认证”。

  • 默认认证插件的确定方式如默认认证插件中所述。

原文:dev.mysql.com/doc/refman/8.0/en/native-pluggable-authentication.html

8.4.1.1 本地可插拔认证

MySQL 包含一个实现本地认证的mysql_native_password插件;即,基于在可插拔认证引入之前使用的密码哈希方法的认证。

注意

从 MySQL 8.0.34 开始,mysql_native_password认证插件已被弃用,并可能在将来的 MySQL 版本中被移除。

以下表显示了服务器端和客户端端的插件名称。

表 8.16 本地密码认证的插件和库名称

插件或文件

插件或文件名

服务器端插件

mysql_native_password

客户端插件

mysql_native_password

库文件

无(插件已内置)

以下各节提供了特定于本地可插拔认证的安装和使用信息:

  • 安装本地可插拔认证
  • 使用本地可插拔认证

有关 MySQL 中可插拔认证的一般信息,请参阅第 8.2.17 节,“可插拔认证”。

安装本地可插拔认证

mysql_native_password插件存在于服务器和客户端形式中:

  • 服务器端插件内置于服务器中,无需显式加载,并且无法通过卸载来禁用它。
  • 客户端插件内置于libmysqlclient客户端库中,并可供链接到libmysqlclient的任何程序使用。
使用本地可插拔认证

MySQL 客户端程序默认使用mysql_native_password--default-auth选项可用作程序可以期望使用的客户端插件的提示:

代码语言:javascript复制
$> mysql --default-auth=mysql_native_password ...

原文:dev.mysql.com/doc/refman/8.0/en/caching-sha2-pluggable-authentication.html

8.4.1.2 缓存 SHA-2 可插拔身份验证

MySQL 提供了两个实现 SHA-256 哈希用于用户帐户密码的身份验证插件:

  • sha256_password:实现基本的 SHA-256 身份验证。
  • caching_sha2_password:实现 SHA-256 身份验证(类似于sha256_password),但在服务器端使用缓存以提高性能,并具有更广泛适用性的附加功能。

本节描述了缓存 SHA-2 身份验证插件。有关原始基本(非缓存)插件的信息,请参见第 8.4.1.3 节,“SHA-256 可插拔身份验证”。

重要

在 MySQL 8.0 中,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插件具有以下优点:

  • 在服务器端,内存中的缓存使得已连接过的用户再次连接时能够更快地重新验证身份。
  • 基于 RSA 的密码交换可用,无论 MySQL 链接到哪个 SSL 库。
  • 支持使用 Unix 套接字文件和共享内存协议的客户端连接。

以下表格显示了服务器端和客户端的插件名称。

表 8.17 SHA-2 身份验证的插件和库名称

插件或文件

插件或文件名

服务器端插件

caching_sha2_password

客户端插件

caching_sha2_password

库文件

无(插件内置)

以下各节提供了特定于缓存 SHA-2 可插拔身份验证的安装和使用信息:

  • 安装 SHA-2 可插拔身份验证
  • 使用 SHA-2 可插拔身份验证
  • SHA-2 可插拔身份验证的缓存操作

有关 MySQL 中可插拔身份验证的一般信息,请参阅第 8.2.17 节,“可插拔身份验证”。

安装 SHA-2 可插拔身份验证

caching_sha2_password插件以服务器和客户端形式存在:

  • 服务器端插件内置于服务器中,无需显式加载,并且无法通过卸载来禁用。
  • 客户端插件内置于libmysqlclient客户端库中,并可供链接到libmysqlclient的任何程序使用。

服务器端插件使用sha2_cache_cleaner审计插件作为辅助工具来执行密码缓存管理。sha2_cache_cleanercaching_sha2_password一样,是内置的,无需安装。

使用 SHA-2 可插拔身份验证

要设置一个使用caching_sha2_password插件进行 SHA-256 密码哈希的帐户,请使用以下语句,其中*password*是所需的帐户密码:

代码语言:javascript复制
CREATE USER 'sha2user'@'localhost'
IDENTIFIED WITH caching_sha2_password BY '*password*';

服务器将caching_sha2_password插件分配给帐户,并使用它使用 SHA-256 加密密码,将这些值存储在mysql.user系统表的pluginauthentication_string列中。

前述说明并不假设caching_sha2_password是默认的身份验证插件。如果caching_sha2_password是默认的身份验证插件,则可以使用更简单的CREATE USER语法。

要将服务器的默认身份验证插件设置为caching_sha2_password,请在服务器选项文件中添加以下行:

代码语言:javascript复制
[mysqld]
default_authentication_plugin=caching_sha2_password

这将导致caching_sha2_password插件默认用于新帐户。因此,可以创建帐户并设置其密码而无需显式命名插件:

代码语言:javascript复制
CREATE USER 'sha2user'@'localhost' IDENTIFIED BY '*password*';

default_authentication_plugin设置为caching_sha2_password的另一个后果是,要使用其他插件进行帐户创建,必须明确指定该插件。例如,要使用mysql_native_password插件,请使用以下语句:

代码语言:javascript复制
CREATE USER 'nativeuser'@'localhost'
IDENTIFIED WITH mysql_native_password BY '*password*';

caching_sha2_password 支持通过安全传输进行连接。如果您按照本节后面给出的 RSA 配置过程,它还支持在未加密连接上使用 RSA 进行加密密码交换。RSA 支持具有以下特点:

  • 在服务器端,两个系统变量命名了 RSA 私钥和公钥对文件:caching_sha2_password_private_key_pathcaching_sha2_password_public_key_path。如果要使用与系统变量默认值不同的名称的密钥文件,则数据库管理员必须在服务器启动时设置这些变量。
  • 服务器使用 caching_sha2_password_auto_generate_rsa_keys 系统变量来确定是否自动生成 RSA 密钥对文件。请参阅 Section 8.3.3, “Creating SSL and RSA Certificates and Keys”。
  • 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选项从服务器请求公钥。以下程序支持这两个选项:mysqlmysqlshmysqladminmysqlbinlogmysqlcheckmysqldumpmysqlimportmysqlpumpmysqlshowmysqlslapmysqltestmysql_upgrade
    • 对于使用 C API 的程序,通过调用mysql_options()来指定 RSA 公钥文件,传递MYSQL_SERVER_PUBLIC_KEY选项和文件名,或者通过传递MYSQL_OPT_GET_SERVER_PUBLIC_KEY选项从服务器请求公钥。
    • 对于副本,使用CHANGE REPLICATION SOURCE TO语句(从 MySQL 8.0.23 开始)或CHANGE MASTER TO语句(在 MySQL 8.0.23 之前)与SOURCE_PUBLIC_KEY_PATH | MASTER_PUBLIC_KEY_PATH选项来指定 RSA 公钥文件,或使用GET_SOURCE_PUBLIC_KEY | GET_MASTER_PUBLIC_KEY选项从源请求公钥。对于组复制,group_replication_recovery_public_key_pathgroup_replication_recovery_get_public_key系统变量具有相同的作用。

    在所有情况下,如果给定指定有效公钥文件的选项,则该选项优先于从服务器请求公钥的选项。

对于使用caching_sha2_password插件的客户端,在连接到服务器时,密码永远不会以明文形式暴露。密码传输的方式取决于是否使用安全连接或 RSA 加密:

  • 如果连接是安全的,则不需要使用 RSA 密钥对。这适用于使用 TLS 加密的 TCP 连接,以及 Unix 套接字文件和共享内存连接。密码以明文形式发送,但由于连接是安全的,无法窃听。
  • 如果连接不安全,则使用 RSA 密钥对。这适用于未使用 TLS 加密的 TCP 连接和命名管道连接。RSA 仅用于客户端和服务器之间的密码交换,以防止密码窗口。当服务器接收到加密密码时,它会对其进行解密。加密中使用了混淆以防止重复攻击。

要在客户端连接过程中使用 RSA 密钥对进行密码交换,请使用以下步骤:

使用 Section 8.3.3, “Creating SSL and RSA Certificates and Keys”中的说明创建 RSA 私钥和公钥对文件。

如果私钥和公钥文件位于数据目录中,并且命名为private_key.pempublic_key.pemcaching_sha2_password_private_key_pathcaching_sha2_password_public_key_path系统变量的默认值),服务器将在启动时自动使用它们。

否则,要显式命名密钥文件,请在服务器选项文件中将系统变量设置为密钥文件名。如果文件位于服务器数据目录中,则无需指定其完整路径名:

代码语言:javascript复制
[mysqld]
caching_sha2_password_private_key_path=myprivkey.pem
caching_sha2_password_public_key_path=mypubkey.pem

如果密钥文件不位于数据目录中,或者要在系统变量值中明确指定其位置,请使用完整路径名:

代码语言:javascript复制
[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系统变量。例如:

代码语言:javascript复制
[mysqld]
caching_sha2_password_digest_rounds=10000

重新启动服务器,然后连接到服务器并检查Caching_sha2_password_rsa_public_key状态变量值。实际显示的值与此处显示的值不同,但应为非空:

代码语言:javascript复制
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 执行密码交换的未加密连接。假设使用未加密连接。例如:

代码语言:javascript复制
$> mysql --ssl-mode=DISABLED -u sha2user -p
Enter password: *password*

对于 sha2user 的此连接尝试,服务器确定 caching_sha2_password 是适当的认证插件并调用它(因为在 CREATE USER 时指定了该插件)。插件发现连接未加密,因此需要使用 RSA 加密传输密码。然而,服务器不会将公钥发送给客户端,客户端也未提供公钥,因此无法加密密码,连接失败:

代码语言:javascript复制
ERROR 2061 (HY000): Authentication plugin 'caching_sha2_password'
reported error: Authentication requires secure connection.

要从服务器请求 RSA 公钥,请指定 --get-server-public-key 选项:

代码语言:javascript复制
$> mysql --ssl-mode=DISABLED -u sha2user -p --get-server-public-key
Enter password: *password*

在这种情况下,服务器将 RSA 公钥发送给客户端,客户端使用它加密密码并将结果返回给服务器。插件在服务器端使用 RSA 私钥解密密码,并根据密码是否正确接受或拒绝连接。

或者,如果客户端有包含服务器所需的 RSA 公钥的本地副本的文件,则可以使用 --server-public-key-path 选项指定该文件:

代码语言:javascript复制
$> 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' 语句并将返回的密钥值保存在文件中。
SHA-2 可插拔认证的缓存操作

在服务器端,caching_sha2_password 插件使用内存中的缓存来更快地对先前连接过的客户端进行认证。条目由账户名/密码哈希对组成。缓存的工作方式如下:

  1. 当客户端连接时,caching_sha2_password 检查客户端和密码是否与某个缓存条目匹配。如果匹配,则认证成功。
  2. 如果没有匹配的缓存条目,插件会尝试根据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 密钥对,直到发生影响该账户的另一个清空缓存事件。(当可以使用缓存时,服务器使用一种不使用明文密码传输且不需要安全连接的挑战-响应机制。)

0 人点赞