8.2.17 插件式认证
当客户端连接到 MySQL 服务器时,服务器使用客户端提供的用户名和客户端主机来选择适当的帐户行从mysql.user
系统表中。然后,服务器验证客户端,确定从帐户行中哪个身份验证插件适用于客户端:
-
如果服务器找不到插件,错误发生,连接尝试被拒绝。
-
否则,服务器调用该插件来验证用户,该插件返回一个状态给服务器,指示用户是否提供了正确的密码并被允许连接。
插件式认证启用了这些重要功能:
-
认证方法的选择。 插件式认证使 DBA 可以轻松地选择和更改用于个别 MySQL 帐户的认证方法。
-
外部认证。 插件式认证使得客户端可以使用适合的认证方法连接到 MySQL 服务器,例如 PAM、Windows 登录 ID、LDAP 或 Kerberos 等外部认证方法。
-
代理用户: 如果用户被允许连接,身份验证插件可以将用户名称返回给服务器,以表示连接用户是另一个用户(代理用户)的代理。连接期间,代理用户将被视为拥有代理用户的权限。在某种意义上,一个用户模拟另一个用户。更多信息,请见第8.2.19节,“代理用户”。
如果您使用--skip-grant-tables
选项启动服务器,身份验证插件将不被使用,即使已加载,因为服务器不执行客户端认证并允许任何客户端连接。由于这非常不安全,如果服务器使用--skip-grant-tables
选项启动,它也将禁用远程连接,并启用skip_networking
。
可用的身份验证插件
MySQL 8.4 提供以下身份验证插件:
-
一个基于native认证的插件,即基于MySQL之前的密码哈希方法的认证。
mysql_native_password
插件实现了基于native密码哈希方法的认证。详见第8.4.1.1节,“Native Pluggable Authentication”。Notemysql_native_password
认证插件已弃用,可能在未来版本的MySQL中被删除。 -
使用SHA-256密码哈希的插件,这种加密方式比native认证更强。详见第8.4.1.2节,“Caching SHA-2 Pluggable Authentication”和第8.4.1.3节,“SHA-256 Pluggable Authentication”。
-
一个客户端插件,发送密码到服务器没有加密或哈希。这个插件与服务器端插件一起使用,需要客户端用户提供的密码。详见第8.4.1.4节,“Client-Side Cleartext Pluggable Authentication”。
-
一个外部认证插件,使用PAM(Pluggable Authentication Modules)使MySQL Server使用PAM认证MySQL用户。这个插件支持代理用户。详见第8.4.1.5节,“PAM Pluggable Authentication”。
-
一个Windows认证插件,使MySQL Server使用Windows服务认证客户端连接。用户可以使用MySQL客户端程序连接到服务器,不需要提供额外的密码。这个插件支持代理用户。详见第8.4.1.6节,“Windows Pluggable Authentication”。
-
插件使用LDAP(Lightweight Directory Access Protocol)认证MySQL用户,访问目录服务如X.500。这个插件支持代理用户。详见第8.4.1.7节,“LDAP Pluggable Authentication”。
-
一个Kerberos认证插件,认证MySQL用户对应Kerberos主体。详见第8.4.1.8节,“Kerberos Pluggable Authentication”。
-
一个插件,禁止所有客户端连接到任何使用它的账户。这个插件的用例包括代理账户不能直接登录,但只能通过代理账户访问,以及需要执行存储程序和视图,但不能暴露给普通用户。详见第8.4.1.9节,“No-Login Pluggable Authentication”。
-
一个插件,用于通过 Unix socket 文件从本地主机连接的客户端进行身份验证。见第8.4.1.10节,“Socket Peer-Credential Pluggable Authentication”。
-
一个插件,使用 FIDO/FIDO2 设备和 WebAuthn 格式对 MySQL 服务器进行身份验证。见第8.4.1.11节,“WebAuthn Pluggable Authentication”。
-
一个测试插件,用于检查帐户凭证并将成功或失败记录到服务器错误日志中。这款插件旨在测试和开发用途,作为身份验证插件的示例。见第8.4.1.12节,“Test Pluggable Authentication”。
关于可插拔身份验证的当前限制,包括哪些连接器支持哪些插件,请见可插拔身份验证限制。
第三方连接器开发者应该阅读该部分,以确定连接器可以使用可插拔身份验证的程度,以及需要采取哪些步骤以提高可插拔身份验证的兼容性。
如果您想编写自己的身份验证插件,请见编写身份验证插件。
本节提供了身份验证插件的通用安装和使用指南。对于特定插件的安装和使用指南,请见第8.4.1节,“Authentication Plugins”。
通常情况下,可插拔身份验证使用服务器和客户端两个相应的插件对,使用身份验证方法如下:
-
如果必要,请安装包含相应插件的库或库。在服务器主机上,安装包含服务器端插件的库,以便服务器可以使用它来身份验证客户端连接。类似地,在每个客户端主机上,安装包含客户端插件的库,以便客户端程序使用。需要安装的身份验证插件不需要安装。
-
对于每个 MySQL 帐户,您需要指定适当的服务器端插件进行身份验证。如果帐户将使用默认身份验证插件,帐户创建语句不需要指定插件。服务器将分配默认身份验证插件,详见默认身份验证插件。
-
当客户端连接时,服务器端插件将告诉客户端程序使用哪个客户端插件进行身份验证。
在帐户使用身份验证方法时,如果该方法是服务器和客户端程序的默认身份验证方法,服务器不需要与客户端通信以确定客户端插件,避免了客户端/服务器交互的回圈。
对于标准的 MySQL 客户端,例如mysql和mysqladmin,可以在命令行中指定--default-auth=
选项,以提供客户端插件的提示,但是服务器将覆盖这个提示,如果服务器端插件与用户账户关联的插件需要不同的客户端插件。plugin_name
如果客户端程序找不到客户端插件库文件,请指定--plugin-dir=
选项,以指示插件库目录位置。dir_name
可插拔身份验证使得 MySQL 账户的身份验证方法更加灵活,但是在某些情况下,客户端连接无法建立,因为客户端和服务器之间的身份验证插件不兼容。
客户端连接到给定账户的给定服务器的通用兼容原则是,客户端和服务器都必须支持账户所需的身份验证方法。因为身份验证方法由身份验证插件实现,客户端和服务器都必须支持账户所需的身份验证插件。
身份验证插件不兼容可以以多种方式出现。例如:
-
使用 MySQL 5.7 客户端从 5.7.22 或更低版本连接到 MySQL 8.4 服务器账户,该账户使用
caching_sha2_password
。这将失败,因为 5.7 客户端不认识插件。 (这个问题在 MySQL 5.7 的 5.7.23 版本中被解决,因为在 MySQL 客户端库和客户端程序中添加了caching_sha2_password
客户端支持。) -
使用 MySQL 5.7 客户端连接到 pre-5.7 服务器账户,该账户使用
mysql_old_password
。这将失败,因为这种连接需要--secure-auth=0
,这已经不再是一个支持的选项。即使支持,这个客户端也不认识插件,因为它在 MySQL 5.7 中被删除了。 -
使用 MySQL 5.7 客户端从社区发行版连接到 MySQL 5.7 企业服务器账户,该账户使用企业版的 LDAP 身份验证插件。这将失败,因为社区客户端没有访问企业插件的权限。
总的来说,这些兼容性问题不会出现在客户端和服务器来自同一个 MySQL 发行版的连接中。然而,在客户端和服务器来自不同 MySQL 系列的连接中,这些问题可能会出现。这些问题是 MySQL 开发过程中的一部分,当 MySQL 引入新的身份验证插件或删除旧的插件时。为了减少不兼容性,定期升级服务器、客户端和连接器。
各种 MySQL 客户端/服务器协议实现存在。libmysqlclient
C API 客户端库是其中一个实现。一些 MySQL 连接器(通常是非 C 语言实现)提供了自己的实现。然而,不同的协议实现可能对插件身份验证方式有不同的处理方式。这一部分描述了协议实现者应该注意的一种身份验证问题。
在客户端/服务器协议中,服务器将连接的客户端告知它认为的默认身份验证插件。如果客户端使用的协议实现尝试加载默认插件,但该插件在客户端不存在,加载操作将失败。这是一个不必要的失败,如果默认插件不是连接到哪个账户所需的插件。
如果客户端/服务器协议实现没有自己的默认身份验证插件,并且总是尝试加载服务器指定的默认插件,它将在该插件不可用时失败。
为了避免这个问题,客户端使用的协议实现应该有自己的默认插件,并且将其作为首选(或者,在加载服务器指定的默认插件失败时, fallback 到默认插件)。示例:
-
在 MySQL 5.7 中,
libmysqlclient
使用默认插件是mysql_native_password
或者通过MYSQL_DEFAULT_AUTH
选项指定的插件,以便于mysql_options()
。 -
当 5.7 客户端尝试连接到 8.4 服务器时,服务器将指定
caching_sha2_password
作为默认身份验证插件,但客户端仍然发送凭证细节,以便于mysql_native_password
或者通过MYSQL_DEFAULT_AUTH
指定的插件。 -
只有在更改插件请求时,客户端才会加载服务器指定的插件,但在这种情况下,它可以是任何插件,取决于用户账户。在这种情况下,客户端必须尝试加载插件,如果插件不可用,错误是不可选的。
插件式认证的限制
本节的第一部分描述了可插拔身份验证框架的通用限制,详见第8.2.17节,“可插拔身份验证”。第二部分描述了第三方连接器开发者如何确定连接器可以利用可插拔身份验证能力的程度,以及如何变得更加兼容。
在这里使用的术语““native authentication””指的是对存储在 mysql.user
系统表中的密码的身份验证。这是老版本 MySQL 服务器提供的身份验证方法,之前可插拔身份验证被实现。"“Windows native authentication”"指的是使用已经登录到 Windows 的用户的凭证,实现了 Windows 本地身份验证插件(简称为““Windows plugin””)。
General 插件式认证 Restrictions
-
Connector/C++: 使用该连接器的客户端只能通过使用本地身份验证的帐户连接到服务器。
例外:连接器支持可插拔身份验证,如果它是动态链接到
libmysqlclient
的,而不是静态链接,并且加载当前版本的libmysqlclient
,或者重新编译连接器以链接到当前的libmysqlclient
。有关编写连接器以处理服务器关于默认服务器端身份验证插件的信息,请见身份验证插件连接器编写考虑。
-
Connector/NET: 使用Connector/NET的客户端可以通过使用本地身份验证或Windows本地身份验证连接到服务器。
-
Connector/PHP: 使用该连接器的客户端只能通过使用本地身份验证连接到服务器,使用MySQL native driver for PHP(
mysqlnd
)编译时。 -
Windows本地身份验证: 通过使用Windows插件连接到服务器需要Windows域设置。没有它,NTLM身份验证将被使用,然后只能使用本地连接,即客户端和服务器必须在同一台计算机上运行。
-
代理用户: 代理用户支持可到达客户端可以连接到通过实现代理用户能力的插件身份验证的帐户 authenticated(例如,PAM和Windows插件支持代理用户)。
mysql_native_password
(已弃用)和sha256_password
身份验证插件默认不支持代理用户,但可以配置以支持;见服务器支持代理用户映射。 -
复制:副本不仅可以使用复制用户帐户进行本地身份验证,还可以通过使用非本地身份验证的复制用户帐户连接到服务器,如果需要的客户端插件可用。如果插件已包含在
libmysqlclient
中,它将默认可用。否则,插件必须在副本侧安装在名为plugin_dir
的目录中。
插件式认证 and Third-Party Connectors
第三方连接器开发者可以根据以下指南来确定连接器是否准备好使用可插拔身份验证功能,并了解如何变得更加兼容:
-
一个未经修改的连接器使用本地验证,并且使用该连接器的客户端只能通过使用本地验证的账户连接到服务器。然而,您应该将连接器测试在最近版本的服务器上,以验证这些连接是否仍然无问题。
例外情况:一个连接器可能不需要任何修改,如果它动态链接到
libmysqlclient
,并且加载当前版本的libmysqlclient
,如果该版本已安装。 -
要使用可插拔身份验证功能,基于
libmysqlclient
的连接器应该重新链接到当前版本的libmysqlclient
。这样可以使连接器支持通过账户连接到需要客户端插件的服务器(例如,PAM身份验证和 Windows 本地身份验证)。重新链接到当前版本的libmysqlclient
也可以使连接器访问安装在默认 MySQL 插件目录(通常是由本地服务器的plugin_dir
系统变量指定的目录)中的客户端插件。如果连接器动态链接到
libmysqlclient
,则必须确保客户端主机上安装了新的libmysqlclient
版本,并且连接器在运行时加载它。 -
另一种方法是将身份验证方法直接实现在客户端/服务器协议中。Connector/NET 使用这种方法来提供 Windows 本地身份验证支持。
-
如果连接器需要从非默认插件目录加载客户端插件,必须实现一些方式让客户端用户指定目录。可能的方法包括命令行选项或环境变量,从而连接器可以获取目录名称。标准 MySQL 客户端程序,如 mysql 和 mysqladmin,实现了一个
--plugin-dir
选项。请参阅C API 客户端插件接口。 -
连接器支持代理用户的支持取决于,正如本节前面所述的身份验证方法是否允许代理用户。