当客户端连接到 MySQL 服务器时,服务器使用客户端提供的用户名和客户端主机从 mysql.user
系统表中选择相应的帐户行。然后服务器对客户端进行身份验证,根据帐户行确定适用于客户端的身份验证插件。
如果服务器找不到该插件,则会发生错误,并且连接尝试将被拒绝。
否则,服务器将调用该插件以对用户进行身份验证,并且该插件会向服务器返回一个状态,指示用户是否提供了正确的密码以及是否允许连接。
可插拔身份验证支持以下重要功能:
身份验证方法的选择。 可插拔身份验证使数据库管理员可以轻松选择和更改用于各个 MySQL 帐户的身份验证方法。
外部身份验证。 可插拔身份验证使客户端可以使用适用于在
mysql.user
系统表以外的其他位置存储凭据的身份验证方法连接到 MySQL 服务器。例如,可以创建插件以使用外部身份验证方法,例如 PAM、Windows 登录 ID、LDAP 或 Kerberos。代理用户: 如果允许用户连接,身份验证插件可以向服务器返回与连接用户的名称不同的用户名,以指示连接用户是另一个用户(被代理用户)的代理。在连接持续期间,出于访问控制的目的,代理用户将被视为具有被代理用户的权限。实际上,一个用户可以模拟另一个用户。有关更多信息,请参阅第 8.2.19 节“代理用户”。
如果使用 --skip-grant-tables
选项启动服务器,即使加载了身份验证插件,也不会使用它们,因为服务器不执行客户端身份验证并允许任何客户端连接。因为这是不安全的,所以如果使用 --skip-grant-tables
选项启动服务器,它还会通过启用 skip_networking
来禁用远程连接。
MySQL 9.0 提供以下身份验证插件:
使用 SHA-256 密码哈希执行身份验证的插件。这比原生身份验证提供的加密更强大。请参阅第 8.4.1.1 节“缓存 SHA-2 可插拔身份验证”和第 8.4.1.2 节“SHA-256 可插拔身份验证”。
一个客户端插件,它将密码发送到服务器,而不进行哈希或加密。此插件与需要完全按照客户端用户提供的密码访问密码的服务器端插件结合使用。请参阅第 8.4.1.3 节“客户端明文可插拔身份验证”。
一个使用 PAM(可插拔身份验证模块)执行外部身份验证的插件,使 MySQL 服务器能够使用 PAM 对 MySQL 用户进行身份验证。此插件也支持代理用户。请参阅第 8.4.1.4 节“PAM 可插拔身份验证”。
一个在 Windows 上执行外部身份验证的插件,使 MySQL 服务器能够使用本地 Windows 服务对客户端连接进行身份验证。登录到 Windows 的用户可以根据其环境中的信息从 MySQL 客户端程序连接到服务器,而无需指定额外的密码。此插件也支持代理用户。请参阅第 8.4.1.5 节“Windows 可插拔身份验证”。
使用 LDAP(轻量级目录访问协议)执行身份验证的插件,通过访问 X.500 等目录服务对 MySQL 用户进行身份验证。这些插件也支持代理用户。请参阅第 8.4.1.6 节“LDAP 可插拔身份验证”。
使用 Kerberos 执行身份验证的插件,用于对与 Kerberos 主体相对应的 MySQL 用户进行身份验证。请参阅第 8.4.1.7 节“Kerberos 可插拔身份验证”。
一个插件,用于阻止所有客户端连接到使用它的任何帐户。此插件的用例包括:永远不允许直接登录但只能通过代理帐户访问的代理帐户,以及必须能够以提升的权限执行存储过程和视图而不向普通用户公开这些权限的帐户。请参阅第 8.4.1.8 节“无登录可插拔身份验证”。
一个插件,用于对从本地主机通过 Unix 套接字文件连接的客户端进行身份验证。请参阅第 8.4.1.9 节“套接字对等凭据可插拔身份验证”。
一个插件,使用带有 FIDO/FIDO2 设备的 WebAuthn 格式对 MySQL 服务器的用户进行身份验证。请参阅第 8.4.1.10 节“WebAuthn 可插拔身份验证”。
一个测试插件,用于检查帐户凭据并将成功或失败记录到服务器错误日志中。此插件用于测试和开发目的,并且作为如何编写身份验证插件的示例。请参阅第 8.4.1.11 节“测试可插拔身份验证”。
有关使用可插拔身份验证的当前限制的信息,包括哪些连接器支持哪些插件,请参阅可插拔身份验证的限制。
第三方连接器开发人员应阅读该部分,以确定连接器可以在多大程度上利用可插拔身份验证功能,以及为提高兼容性应采取哪些步骤。
如果您有兴趣编写自己的身份验证插件,请参阅编写身份验证插件。
本节提供有关安装和使用身份验证插件的一般说明。有关特定插件的说明,请参阅第 8.4.1 节“身份验证插件”下描述该插件的部分。
通常,可插拔身份验证在服务器端和客户端使用一对相应的插件,因此您可以像这样使用给定的身份验证方法
如有必要,请安装包含相应插件的插件库。在服务器主机上,安装包含服务器端插件的库,以便服务器可以使用它来验证客户端连接。同样,在每个客户端主机上,安装包含客户端程序使用的客户端插件的库。内置的身份验证插件无需安装。
对于您创建的每个 MySQL 帐户,请指定用于身份验证的相应服务器端插件。如果帐户要使用默认的身份验证插件,则帐户创建语句无需显式指定插件。服务器将分配默认的身份验证插件,该插件的确定方式如默认身份验证插件中所述。
当客户端连接时,服务器端插件会告诉客户端程序使用哪个客户端插件进行身份验证。
如果帐户使用的身份验证方法是服务器和客户端程序的默认方法,则服务器无需与客户端通信使用哪个客户端插件,并且可以避免客户端/服务器协商中的往返。
对于标准的 MySQL 客户端(如mysql和mysqladmin),可以在命令行中将--default-auth=
选项指定为有关程序可以使用哪个客户端插件的提示,尽管如果与用户帐户关联的服务器端插件需要不同的客户端插件,则服务器会覆盖此选项。plugin_name
如果客户端程序找不到客户端插件库文件,请指定--plugin-dir=
选项以指示插件库目录的位置。dir_name
可插拔身份验证使 MySQL 帐户的身份验证方法选择更加灵活,但在某些情况下,由于客户端和服务器之间的身份验证插件不兼容,客户端连接无法建立。
成功建立客户端连接到给定服务器上的给定帐户的一般兼容性原则是,客户端和服务器都必须支持帐户所需的身份验证方法。由于身份验证方法是由身份验证插件实现的,因此客户端和服务器都必须支持帐户所需的身份验证插件。
身份验证插件不兼容可以通过多种方式出现。例如:
使用 5.7.22 或更低版本的 MySQL 5.7 客户端连接到使用
caching_sha2_password
进行身份验证的 MySQL 9.0 服务器帐户。这将失败,因为 5.7 客户端无法识别该插件。(此问题已在 MySQL 5.7 的 5.7.23 版本中得到解决,当时caching_sha2_password
客户端支持已添加到 MySQL 客户端库和客户端程序中。)使用 MySQL 5.7 客户端连接到使用
mysql_old_password
进行身份验证的 5.7 之前的服务器帐户。这将因多种原因而失败。首先,此类连接需要--secure-auth=0
,而这不再是一个受支持的选项。即使它受支持,5.7 客户端也无法识别该插件,因为它已在 MySQL 5.7 中被移除。使用来自社区发行版的 MySQL 5.7 客户端连接到使用其中一个仅限企业版使用的 LDAP 身份验证插件进行身份验证的 MySQL 5.7 企业版服务器帐户。这将失败,因为社区客户端无法访问企业版插件。
通常,当在来自同一 MySQL 发行版的客户端和服务器之间建立连接时,不会出现这些兼容性问题。当在来自不同 MySQL 系列的客户端和服务器之间建立连接时,就会出现这些问题。当 MySQL 引入新的身份验证插件或移除旧的插件时,这些问题在开发过程中是固有的。为了最大限度地减少不兼容的可能性,请及时定期升级服务器、客户端和连接器。
MySQL 客户端/服务器协议存在多种实现。libmysqlclient
C API 客户端库就是其中一种实现。一些 MySQL 连接器(通常不是用 C 编写的)提供了它们自己的实现。但是,并非所有协议实现都以相同的方式处理插件身份验证。本节描述了协议实现者应考虑的身份验证问题。
在客户端/服务器协议中,服务器会告诉连接的客户端它认为哪个身份验证插件是默认插件。如果客户端使用的协议实现尝试加载默认插件,并且该插件在客户端不存在,则加载操作将失败。如果默认插件不是客户端尝试连接的帐户实际需要的插件,那么这就是一个不必要的失败。
如果客户端/服务器协议实现没有自己的默认身份验证插件概念,并且始终尝试加载服务器指定的默认插件,则如果该插件不可用,它将失败并报错。
为了避免此问题,客户端使用的协议实现应具有自己的默认插件,并应将其用作首选(或者,如果无法加载服务器指定的默认插件,则回退到此默认插件)。例如:
在 MySQL 5.7 中,
libmysqlclient
使用mysql_native_password
或通过mysql_options()
的MYSQL_DEFAULT_AUTH
选项指定的插件作为其默认选择。当 5.7 客户端尝试连接到 9.0 服务器时,服务器会指定
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:使用此连接器的客户端只能通过使用本地身份验证的帐户连接到服务器,前提是使用 PHP 的 MySQL 本地驱动程序(
mysqlnd
)进行编译。Windows 本地身份验证:通过使用 Windows 插件的帐户进行连接需要 Windows 域设置。如果没有它,将使用 NTLM 身份验证,并且只能进行本地连接;也就是说,客户端和服务器必须在同一台计算机上运行。
代理用户: 在客户端可以通过使用实现了代理用户功能的插件(即可以返回不同于连接用户的用户名的插件)进行身份验证的帐户连接的情况下,支持代理用户。例如,PAM 和 Windows 插件支持代理用户。
sha256_password
身份验证插件默认不支持代理用户,但可以配置为支持代理用户;请参阅服务器对代理用户映射的支持。复制: 副本不仅可以使用原生身份验证来使用复制用户帐户,而且如果所需的客户端插件可用,还可以通过使用非原生身份验证的复制用户帐户进行连接。如果插件内置于
libmysqlclient
中,则默认情况下可用。否则,必须在副本端的plugin_dir
系统变量命名的目录中安装插件。
可插拔身份验证和第三方连接器
第三方连接器开发人员可以使用以下指南来确定连接器是否已准备好利用可插拔身份验证功能,以及为提高兼容性应采取哪些步骤。
未进行任何更改的现有连接器使用原生身份验证,并且使用该连接器的客户端只能通过使用原生身份验证的帐户连接到服务器。 但是,您应该使用最新版本的服务器测试连接器,以验证此类连接是否仍然可以正常工作。
例外情况:如果连接器动态链接到
libmysqlclient
(而不是静态链接),并且如果安装了当前版本的libmysqlclient
,则它会加载该版本,在这种情况下,连接器可能会在没有任何更改的情况下使用可插拔身份验证。为了利用可插拔身份验证功能,基于
libmysqlclient
的连接器应该重新链接到当前版本的libmysqlclient
。这使连接器能够支持通过现在内置于libmysqlclient
中的客户端插件(例如 PAM 身份验证所需的明文插件和 Windows 原生身份验证所需的 Windows 插件)进行的连接。与当前的libmysqlclient
链接还可以使连接器访问安装在默认 MySQL 插件目录(通常是本地服务器的plugin_dir
系统变量的默认值命名的目录)中的客户端插件。如果连接器动态链接到
libmysqlclient
,则必须确保在客户端主机上安装了更新版本的libmysqlclient
,并且连接器在运行时加载了该版本。连接器支持给定身份验证方法的另一种方法是在客户端/服务器协议中直接实现它。Connector/NET 使用这种方法来提供对 Windows 原生身份验证的支持。
如果连接器应该能够从默认插件目录以外的目录加载客户端插件,则它必须实现某种方法,以便客户端用户指定该目录。这方面的可能性包括命令行选项或环境变量,连接器可以从中获取目录名称。标准 MySQL 客户端程序(例如 mysql 和 mysqladmin)实现了
--plugin-dir
选项。另请参阅C API 客户端插件接口。如本节前面所述,连接器对代理用户的支持取决于它支持的身份验证方法是否允许代理用户。