当客户端连接到 MySQL 服务器时,服务器使用客户端提供的用户名和客户端主机来选择适合的帐户行从 mysql.user
系统表中。然后,服务器对客户端进行身份验证,确定从帐户行中哪个身份验证插件适用于客户端:
-
如果服务器无法找到插件,将发生错误并拒绝连接尝试。
-
否则,服务器调用该插件来身份验证用户,并且插件将状态返回给服务器,指示用户是否提供了正确的密码并被允许连接。
插件式身份验证启用了这些重要功能:
-
身份验证方法选择 插件式身份验证使 DBA 能够轻松地选择和更改 MySQL 帐户的身份验证方法。
-
外部身份验证 插件式身份验证使客户端能够使用外部身份验证方法连接到 MySQL 服务器,例如 PAM、Windows 登录 ID、LDAP 或 Kerberos。
-
代理用户 如果用户被允许连接,身份验证插件可以将不同的用户名返回给服务器,以指示连接用户是另一个用户(代理用户)的代理。在连接期间,代理用户被视为拥有代理用户的权限。实际上,一个用户模拟另一个用户。有关更多信息,请参阅 第 8.2.19 节,“代理用户”。
如果您使用 --skip-grant-tables
选项启动服务器,即使加载了身份验证插件,也不会使用它们,因为服务器不执行客户端身份验证并允许任何客户端连接。由于这非常不安全,因此如果服务器使用 --skip-grant-tables
选项启动,也会禁用远程连接,启用 skip_networking
。
MySQL 8.3 提供了这些身份验证插件:
-
一个插件执行本机身份验证,即基于密码哈希方法的身份验证,该方法来自于 MySQL 引入插件式身份验证之前。
mysql_native_password
插件实现了基于本机密码哈希方法的身份验证。请参阅 第 8.4.1.1 节,“本机插件式身份验证”。Notemysql_native_password
身份验证插件已弃用,并将在未来版本的 MySQL 中删除。 -
插件执行使用 SHA-256 密码哈希的身份验证,这比本机身份验证提供了更强的加密。请参阅 第 8.4.1.2 节,“缓存 SHA-2 插件式身份验证” 和 第 8.4.1.3 节,“SHA-256 插件式身份验证”。
-
客户端插件,发送未经哈希或加密的密码到服务器。此插件与服务器端插件结合使用,服务器端插件需要访问客户端用户提供的原始密码。参见第 8.4.1.4 节,“客户端明文可插拔身份验证”。
-
使用 PAM(可插拔身份验证模块)执行外部身份验证的插件,启用 MySQL 服务器使用 PAM 对 MySQL 用户进行身份验证。此插件还支持代理用户。参见第 8.4.1.5 节,“PAM 可插拔身份验证”。
-
在 Windows 上执行外部身份验证的插件,启用 MySQL 服务器使用本机 Windows 服务对客户端连接进行身份验证。已经登录 Windows 的用户可以从 MySQL 客户端程序连接到服务器,基于环境中的信息,无需指定额外的密码。此插件还支持代理用户。参见第 8.4.1.6 节,“Windows 可插拔身份验证”。
-
使用 LDAP(轻量级目录访问协议)对 MySQL 用户进行身份验证的插件,通过访问目录服务,如 X.500。此插件还支持代理用户。参见第 8.4.1.7 节,“LDAP 可插拔身份验证”。
-
使用 Kerberos 对 MySQL 用户进行身份验证的插件,认证对应 Kerberos 主体的用户。参见第 8.4.1.8 节,“Kerberos 可插拔身份验证”。
-
禁止所有客户端连接到使用该插件的任何账户的插件。使用案例包括代理账户,不能直接登录,但只能通过代理账户访问,以及需要执行存储程序和视图的账户,但不暴露这些权限给普通用户。参见第 8.4.1.9 节,“无登录可插拔身份验证”。
-
认证通过 Unix 套接字文件连接到本地主机的客户端的插件。参见第 8.4.1.10 节,“套接字对等凭证可插拔身份验证”。
-
使用 WebAuthn 格式和 FIDO/FIDO2 设备对 MySQL 服务器进行身份验证的插件。参见第 8.4.1.11 节,“WebAuthn 可插拔身份验证”。
-
使用 FIDO 身份验证对 MySQL 服务器进行身份验证的插件。参见第 8.4.1.12 节,“FIDO 可插拔身份验证”。
Noteauthentication_fido
和authentication_fido_client
身份验证插件已弃用,并将在未来版本的 MySQL 中删除。 -
一个测试插件,检查账户凭证并将成功或失败记录到服务器错误日志中。此插件旨在测试和开发目的,并作为编写身份验证插件的示例。参见第 8.4.1.13 节,“测试可插拔身份验证”。
有关可插拔身份验证使用的当前限制,包括哪些连接器支持哪些插件,请参见可插拔身份验证限制。
第三方连接器开发者应该阅读该节,以确定连接器可以利用可插拔身份验证功能的程度,并采取步骤以变得更加兼容。
如果您想编写自己的身份验证插件,请参见编写身份验证插件。
The CREATE USER
和 ALTER USER
语句具有指定账户身份验证方式的语法。一些形式的语法不明确指定身份验证插件(没有 IDENTIFIED WITH
子句)。例如:
CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'password';
在这种情况下,服务器将默认身份验证插件分配给账户。
随着多因素身份验证的引入,可以有多达三个子句指定帐户身份验证的方式。确定默认身份验证插件的规则是特定于因子的:
-
因子 1:如果
身份验证策略
元素 1 指定了身份验证插件,那么该插件就是默认的。如果身份验证策略
元素 1 是*
,那么默认身份验证插件
的值就是默认的。根据上述规则,以下语句创建了一个双因素身份验证帐户,其中第一个因素身份验证方法由
身份验证策略
或默认身份验证插件
设置确定:CREATE USER 'wei'@'localhost' IDENTIFIED BY 'password' AND IDENTIFIED WITH authentication_ldap_simple;
同样,这个示例创建了一个三因素身份验证帐户:
CREATE USER 'mateo'@'localhost' IDENTIFIED BY 'password' AND IDENTIFIED WITH authentication_ldap_simple AND IDENTIFIED WITH authentication_webauthn;
您可以使用
SHOW CREATE USER
查看应用的身份验证方法。 -
因子 2 或 3:如果相应的
身份验证策略
元素指定了身份验证插件,那么该插件就是默认的。如果身份验证策略
元素是*
或空的,那么没有默认的;尝试定义帐户身份验证方法而不指定插件将是一个错误,如以下示例所示:mysql> CREATE USER 'sofia'@'localhost' IDENTIFIED WITH authentication_ldap_simple AND IDENTIFIED BY 'abc'; ERROR 1524 (HY000): Plugin '' is not loaded mysql> CREATE USER 'sofia'@'localhost' IDENTIFIED WITH authentication_ldap_simple AND IDENTIFIED BY 'abc'; ERROR 1524 (HY000): Plugin '*' is not loaded
本节提供了安装和使用身份验证插件的一般说明。对于特定插件的说明,请参阅 第 8.4.1 节,“身份验证插件”。
一般来说,插件身份验证使用服务器端和客户端对应的插件,因此您可以像这样使用身份验证方法:
-
如果必要,安装插件库或包含适当插件的库。在服务器主机上,安装包含服务器端插件的库,以便服务器可以使用它来身份验证客户端连接。类似地,在每个客户端主机上,安装包含客户端插件的库,以便客户端程序使用。内置的身份验证插件无需安装。
-
对于每个 MySQL 帐户,您创建的帐户,指定适当的服务器端插件用于身份验证。如果帐户使用默认身份验证插件,帐户创建语句无需明确指定插件。服务器将分配默认身份验证插件,如 默认身份验证插件 所述。
-
当客户端连接时,服务器端插件告诉客户端程序使用哪个客户端插件进行身份验证。
在帐户使用服务器和客户端程序的默认身份验证方法的情况下,服务器无需与客户端通信以确定客户端插件的使用,从而避免了客户端/服务器协商的往返。
对于标准的 MySQL 客户端程序,如 mysql 和 mysqladmin,可以在命令行上指定 --default-auth=
选项作为客户端程序可以期望使用的客户端插件的提示,尽管服务器可能会覆盖该选项以使用不同的客户端插件。plugin_name
如果客户端程序找不到客户端插件库文件,可以指定 --plugin-dir=
选项以指示插件库目录的位置。dir_name
插件式身份验证使 MySQL 账户的身份验证方法选择更加灵活,但是在某些情况下,客户端连接无法建立是由于客户端和服务器之间的身份验证插件不兼容。
客户端成功连接到给定服务器上的给定账户的通用兼容性原则是,客户端和服务器都必须支持账户所需的身份验证 方法。因为身份验证方法是由身份验证插件实现的,因此客户端和服务器都必须支持账户所需的身份验证 插件。
身份验证插件不兼容可能以各种方式出现。例如:
-
使用 MySQL 5.7 客户端从 5.7.22 或更低版本连接到 MySQL 8.3 服务器账户,该账户使用
caching_sha2_password
进行身份验证。这将失败,因为 5.7 客户端不认识该插件。(这个问题在 MySQL 5.7 中解决了,因为从 5.7.23 开始,caching_sha2_password
客户端支持添加到了 MySQL 客户端库和客户端程序中。) -
使用 MySQL 5.7 客户端连接到 pre-5.7 服务器账户,该账户使用
mysql_old_password
进行身份验证。这将失败,因为该连接需要--secure-auth=0
,该选项不再受支持。即使支持,该 5.7 客户端也不认识该插件,因为它在 MySQL 5.7 中被删除。 -
使用 MySQL 5.7 客户端从 Community 发行版连接到 MySQL 5.7 Enterprise 服务器账户,该账户使用 LDAP 身份验证插件之一进行身份验证。这将失败,因为 Community 客户端没有访问 Enterprise 插件的权限。
一般来说,这些兼容性问题不会在同一个 MySQL 发行版中的客户端和服务器之间出现。当连接来自不同 MySQL 系列的客户端和服务器时,问题可能会出现。这些问题是 MySQL 开发过程中的固有问题,当 MySQL 引入新身份验证插件或删除旧插件时。为了尽量减少不兼容性的可能性,请定期升级服务器、客户端和连接器。
存在多种 MySQL 客户端/服务器协议实现。 libmysqlclient
C API 客户端库是一个实现。一些 MySQL 连接器(通常不是用 C 编写的)提供了自己的实现。然而,不是所有协议实现都以相同的方式处理插件身份验证。这一节描述了协议实现者应该注意的身份验证问题。
在客户端/服务器协议中,服务器告诉连接客户端它认为的默认身份验证插件。如果协议实现使用的客户端尝试加载默认插件并且该插件不存在于客户端侧,则加载操作将失败。这是一个不必要的失败,如果默认插件不是账户实际所需的插件。
如果客户端/服务器协议实现没有自己的默认身份验证插件,并总是尝试加载服务器指定的默认插件,它将在该插件不存在时失败。
为了避免这个问题,客户端使用的协议实现应该有自己的默认插件,并将其作为首选(或者,在失败时回退到默认插件)。例如:
-
在 MySQL 5.7 中,
libmysqlclient
使用mysql_native_password
或通过MYSQL_DEFAULT_AUTH
选项指定的插件作为其默认选择。 -
当 5.7 客户端尝试连接到 8.3 服务器时,服务器指定
caching_sha2_password
作为其默认身份验证插件,但客户端仍然根据mysql_native_password
或通过MYSQL_DEFAULT_AUTH
指定的插件发送凭证详细信息。 -
客户端仅在更改插件请求时加载服务器指定的插件,但在那种情况下它可以是任何插件,取决于用户账户。在这种情况下,客户端必须尝试加载插件,如果该插件不存在,则错误是不可避免的。
本节的第一部分描述了可插拔身份验证框架的通用限制,详见第 8.2.17 节,“可插拔身份验证”。第二部分描述了第三方连接器开发者如何确定连接器可以利用可插拔身份验证功能的程度,以及如何采取步骤以变得更加兼容。
这里使用的术语"“本机身份验证”"是指对存储在 mysql.user
系统表中的密码的身份验证。这是旧版本 MySQL 服务器提供的身份验证方法,在可插拔身份验证实现之前。“Windows 本机身份验证”是指使用已经登录到 Windows 的用户的凭证进行身份验证,由 Windows 本机身份验证插件(简称“Windows 插件”)实现。
通用可插拔身份验证限制
-
Connector/C++: 使用该连接器的客户端只能通过使用本机身份验证的账户连接到服务器。
例外:如果连接器是动态链接到
libmysqlclient
的,并且加载当前版本的libmysqlclient
,或者如果连接器从源代码重新编译以链接到当前libmysqlclient
,那么它支持可插拔身份验证。有关编写连接器以处理服务器关于默认服务器端身份验证插件的信息,请参阅 身份验证插件连接器编写注意事项。
-
Connector/NET: 使用 Connector/NET 的客户端可以通过使用本机身份验证或 Windows 本机身份验证的账户连接到服务器。
-
Connector/PHP: 使用该连接器的客户端只能通过使用本机身份验证的账户连接到服务器,当使用 MySQL 本机驱动程序 для PHP (
mysqlnd
) 编译时。 -
Windows 本机身份验证: 通过使用 Windows 插件连接到账户需要 Windows 域设置。否则,将使用 NTLM 身份验证,只能进行本地连接;也就是说,客户端和服务器必须在同一台计算机上运行。
-
代理用户: 代理用户支持可用,以便客户端可以通过使用插件身份验证的账户连接到服务器,该插件可以返回与连接用户不同的用户名。例如,PAM 和 Windows 插件支持代理用户。
mysql_native_password
(已弃用)和sha256_password
身份验证插件不支持代理用户,默认情况下,但可以配置以支持;请参阅 服务器支持代理用户映射。 -
复制: 副本可以不仅使用本机身份验证的复制用户账户,还可以通过使用非本机身份验证的复制用户账户连接到服务器,如果所需的客户端插件可用。如果插件是内置在
libmysqlclient
中的,那么它默认可用。否则,插件必须在副本侧的目录中安装,该目录由副本的plugin_dir
系统变量命名。
可插拔身份验证和第三方连接器
第三方连接器开发者可以使用以下指南来确定连接器可以利用可插拔身份验证功能的程度,以及如何采取步骤以变得更加兼容:
-
如果连接器没有进行任何更改,则使用本机身份验证,客户端可以仅通过使用本机身份验证的帐户连接到服务器。然而,您应该测试连接器以最近版本的服务器,以验证这些连接是否仍然可以正常工作。
例外:如果连接器动态链接到
libmysqlclient
(而不是静态链接),并加载当前版本的libmysqlclient
(如果已安装),那么它可能不需要进行任何更改就可以使用插件式身份验证。 -
要利用插件式身份验证功能,基于
libmysqlclient
的连接器应该重新链接到当前版本的libmysqlclient
。这样可以使连接器支持通过需要客户端插件的帐户连接(例如,PAM 身份验证所需的明文插件和 Windows 本机身份验证所需的 Windows 插件)。链接到当前libmysqlclient
也使连接器可以访问客户端插件目录(通常是服务器的plugin_dir
系统变量的默认值所指定的目录)中的插件。如果连接器动态链接到
libmysqlclient
,那么必须确保客户端主机上安装了最新版本的libmysqlclient
,并且连接器在运行时加载它。 -
连接器支持特定身份验证方法的另一种方式是直接在客户端/服务器协议中实现它。Connector/NET 使用这种方法来提供 Windows 本机身份验证支持。
-
如果连接器需要从默认插件目录以外的目录加载客户端插件,那么它必须实现某种方式,以便客户端用户可以指定目录。可能的方法包括命令行选项或环境变量,从中连接器可以获取目录名称。标准 MySQL 客户端程序,如 mysql 和 mysqladmin,实现了
--plugin-dir
选项。另请参阅 C API 客户端插件接口。 -
连接器对代理用户的支持取决于它支持的身份验证方法是否允许代理用户,如本节前面所述。