MySQL8 中文参考(二十七)
原文:
dev.mysql.com/doc/refman/8.0/en/sha256-pluggable-authentication.html
8.4.1.3 SHA-256 可插拔认证
MySQL 提供了两个认证插件,用于实现 SHA-256 哈希算法对用户账户密码进行加密:
-
sha256_password:实现基本的 SHA-256 认证。 -
caching_sha2_password:实现 SHA-256 认证(类似于sha256_password),但在服务器端使用缓存以提高性能,并具有更广泛适用性的附加功能。
本节描述了原始的非缓存 SHA-2 认证插件。有关缓存插件的信息,请参见第 8.4.1.2 节,“缓存 SHA-2 可插拔认证”。
重要提示
在 MySQL 8.0 中,默认认证插件为caching_sha2_password而不是mysql_native_password。有关此更改对服务器操作以及服务器与客户端和连接器的兼容性的影响的信息,请参见 caching_sha2_password 作为首选认证插件。
由于caching_sha2_password是 MySQL 8.0 中的默认认证插件,并提供了sha256_password认证插件的全部功能,因此sha256_password已被弃用;预计在未来的 MySQL 版本中将其移除。使用sha256_password进行认证的 MySQL 账户应迁移到使用caching_sha2_password。
重要提示
要使用使用sha256_password插件进行认证连接到服务器,您必须使用支持密码交换的 TLS 连接或 RSA 密钥对的非加密连接,如本节后面描述的那样。无论哪种方式,sha256_password插件都使用 MySQL 的加密功能。参见第 8.3 节,“使用加密连接”。
注意
在sha256_password中,“sha256”指的是插件用于加密的 256 位摘要长度。在caching_sha2_password中,“sha2”更普遍地指 SHA-2 类加密算法,256 位加密是其中的一个实例。后者的名称选择为未来扩展可能的摘要长度留出了空间,而不更改插件名称。
以下表格显示了服务器端和客户端端的插件名称。
表 8.18 SHA-256 认证的插件和库名称
| 插件或文件 | 插件或文件名 |
|---|---|
| 服务器端插件 | sha256_password |
| 客户端端插件 | sha256_password |
| 库文件 | 无(插件已内置) |
以下各节提供了特定于 SHA-256 可插拔认证的安装和使用信息:
-
安装 SHA-256 可插拔认证
-
使用 SHA-256 可插拔认证
有关 MySQL 中可插拔认证的一般信息,请参见第 8.2.17 节,“可插拔认证”。
安装 SHA-256 可插拔认证
sha256_password插件以服务器和客户端形式存在:
-
服务器端插件内置于服务器中,无需显式加载,并且无法通过卸载来禁用。
-
客户端端插件内置于
libmysqlclient客户端库中,并可供链接到libmysqlclient的任何程序使用。
使用 SHA-256 可插拔认证
要设置使用sha256_password插件进行 SHA-256 密码哈希的帐户,请使用以下语句,其中*password*是所需的帐户密码:
CREATE USER 'sha256user'@'localhost'
IDENTIFIED WITH sha256_password BY '*password*';
服务器将sha256_password插件分配给帐户,并使用它使用 SHA-256 加密密码,将这些值存储在mysql.user系统表的plugin和authentication_string列中。
上述说明不假设sha256_password是默认认证插件。如果sha256_password是默认认证插件,则可以使用更简单的CREATE USER语法。
要将服务器的默认认证插件设置为sha256_password启动服务器,请在服务器选项文件中添加以下行:
[mysqld]
default_authentication_plugin=sha256_password
这将导致默认情况下新帐户使用sha256_password插件。因此,可以创建帐户并设置其密码而无需明确命名插件:
CREATE USER 'sha256user'@'localhost' IDENTIFIED BY '*password*';
将default_authentication_plugin设置为sha256_password的另一个后果是,要使用其他插件进行帐户创建,必须明确指定该插件。例如,要使用mysql_native_password插件,请使用以下语句:
CREATE USER 'nativeuser'@'localhost'
IDENTIFIED WITH mysql_native_password BY '*password*';
sha256_password支持通过安全传输进行连接。如果 MySQL 使用 OpenSSL 编译,并且要连接的 MySQL 服务器配置为支持 RSA(使用本节后面给出的 RSA 配置过程),sha256_password还支持在未加密连接上使用 RSA 进行加密密码交换。
RSA 支持具有以下特征:
-
在服务器端,两个系统变量命名 RSA 私钥和公钥对文件:
sha256_password_private_key_path和sha256_password_public_key_path。如果要使用与系统变量默认值不同的名称的密钥文件,数据库管理员必须在服务器启动时设置这些变量。 -
服务器使用
sha256_password_auto_generate_rsa_keys系统变量来确定是否自动生成 RSA 密钥对文件。请参阅第 8.3.3 节,“创建 SSL 和 RSA 证书和密钥”。 -
Rsa_public_key状态变量显示sha256_password认证插件使用的 RSA 公钥值。 -
拥有 RSA 公钥的客户端可以在连接过程中与服务器执行基于 RSA 密钥对的密码交换,如后文所述。
-
对于使用
sha256_password和 RSA 密钥对进行密码交换进行身份验证的帐户的连接,服务器根据需要向客户端发送 RSA 公钥。但是,如果客户端主机上有公钥的副本,则客户端可以使用它来节省客户端/服务器协议中的往返:-
对于这些命令行客户端,请使用
--server-public-key-path选项来指定 RSA 公钥文件:mysql, mysqladmin, mysqlbinlog, mysqlcheck, mysqldump, mysqlimport, mysqlpump, mysqlshow, mysqlslap, mysqltest, mysql_upgrade. -
对于使用 C API 的程序,请调用
mysql_options()来通过传递MYSQL_SERVER_PUBLIC_KEY选项和文件名指定 RSA 公钥文件。 -
对于副本,使用
CHANGE REPLICATION SOURCE TO语句(从 MySQL 8.0.23 开始)或CHANGE MASTER TO语句(在 MySQL 8.0.23 之前)与SOURCE_PUBLIC_KEY_PATH|MASTER_PUBLIC_KEY_PATH选项来指定 RSA 公钥文件。对于组复制,group_replication_recovery_get_public_key系统变量具有相同的作用。
-
对于使用sha256_password插件的客户端,在连接到服务器时,密码永远不会以明文形式暴露。密码传输的方式取决于是否使用安全连接或 RSA 加密:
-
如果连接是安全的,则不需要使用 RSA 密钥对,也不会使用。这适用于使用 TLS 加密的连接。密码以明文形式发送,但无法被窃听,因为连接是安全的。
注意
与
caching_sha2_password不同,sha256_password插件不将共享内存连接视为安全,即使共享内存传输默认安全。 -
如果连接不安全,并且存在 RSA 密钥对,则连接保持未加密。这适用于未使用 TLS 加密的连接。RSA 仅用于客户端和服务器之间的密码交换,以防止密码窃听。当服务器接收到加密密码时,它会对其进行解密。在加密中使用了一种混淆以防止重复攻击。
-
如果未使用安全连接且不可用 RSA 加密,则连接尝试将失败,因为密码无法在未以明文形式暴露的情况下发送。
注意
要使用sha256_password进行 RSA 密码加密,客户端和服务器都必须使用 OpenSSL 进行编译,而不仅仅是其中一个。
假设 MySQL 已使用 OpenSSL 编译,请使用以下过程在客户端连接过程中启用 RSA 密钥对用于密码交换:
-
使用 Section 8.3.3, “Creating SSL and RSA Certificates and Keys”中的说明创建 RSA 私钥和公钥对文件。
-
如果私钥和公钥文件位于数据目录中,并且命名为
private_key.pem和public_key.pem(sha256_password_private_key_path和sha256_password_public_key_path系统变量的默认值),服务器将在启动时自动使用它们。否则,要显式命名关键文件,请在服务器选项文件中设置系统变量为关键文件名。如果文件位于服务器数据目录中,则无需指定其完整路径名:
[mysqld] sha256_password_private_key_path=myprivkey.pem sha256_password_public_key_path=mypubkey.pem如果密钥文件不位于数据目录中,或者要在系统变量值中明确它们的位置,请使用完整路径名:
[mysqld] sha256_password_private_key_path=/usr/local/mysql/myprivkey.pem sha256_password_public_key_path=/usr/local/mysql/mypubkey.pem -
重新启动服务器,然后连接到服务器并检查
Rsa_public_key状态变量值。实际显示的值与此处显示的值不同,但应为非空:mysql> SHOW STATUS LIKE 'Rsa_public_key'\G *************************** 1\. row *************************** Variable_name: Rsa_public_key Value: -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDO9nRUDd+KvSZgY7cNBZMNpwX6 MvE1PbJFXO7u18nJ9lwc99Du/E7lw6CVXw7VKrXPeHbVQUzGyUNkf45Nz/ckaaJa aLgJOBCIDmNVnyU54OT/1lcs2xiyfaDMe8fCJ64ZwTnKbY2gkt1IMjUAB5Ogd5kJ g8aV7EtKwyhHb0c30QIDAQAB -----END PUBLIC KEY-----如果值为空,则服务器发现密钥文件存在问题。请检查错误日志以获取诊断信息。
在服务器配置了 RSA 密钥文件之后,使用sha256_password插件进行身份验证的帐户可以选择使用这些密钥文件连接到服务器。如前所述,这些帐户可以使用安全连接(在这种情况下不使用 RSA)或使用 RSA 执行密码交换的未加密连接。假设使用未加密连接。例如:
$> mysql --ssl-mode=DISABLED -u sha256user -p
Enter password: *password*
对于sha256user的此连接尝试,服务器确定sha256_password是适当的身份验证插件并调用它(因为在CREATE USER时指定了该插件)。插件发现连接未加密,因此需要使用 RSA 加密传输密码。在这种情况下,插件将 RSA 公钥发送给客户端,客户端使用它加密密码并将结果返回给服务器。插件在服务器端使用 RSA 私钥解密密码,并根据密码是否正确接受或拒绝连接。
服务器根据需要向客户端发送 RSA 公钥。但是,如果客户端有包含服务器所需的 RSA 公钥的本地副本的文件,可以使用--server-public-key-path选项指定该文件:
$> mysql --ssl-mode=DISABLED -u sha256user -p --server-public-key-path=*file_name*
Enter password: *password*
由--server-public-key-path选项指定的文件中的公钥值应与由sha256_password_public_key_path系统变量指定的服务器端文件中的密钥值相同。如果密钥文件包含有效的公钥值但值不正确,则会发生访问被拒绝的错误。如果密钥文件不包含有效的公钥,则客户端程序无法使用它。在这种情况下,sha256_password插件将向客户端发送公钥,就好像没有指定--server-public-key-path选项一样。
客户端用户可以通过两种方式获取 RSA 公钥:
-
数据库管理员可以提供公钥文件的副本。
-
客户端用户可以通过其他方式连接到服务器,使用
SHOW STATUS LIKE 'Rsa_public_key'语句并将返回的密钥值保存在文件中。
原文:
dev.mysql.com/doc/refman/8.0/en/cleartext-pluggable-authentication.html
8.4.1.4 客户端端明文可插拔身份验证
有一个客户端身份验证插件可用,使客户端可以将密码以明文形式发送到服务器,而无需进行哈希或加密。此插件内置于 MySQL 客户端库中。
以下表格显示了插件名称。
Table 8.19 Plugin and Library Names for Cleartext Authentication
| 插件或文件 | 插件或文件名 |
|---|---|
| 服务器端插件 | 无,请参见讨论 |
| 客户端插件 | mysql_clear_password |
| 库文件 | 无(插件内置) |
许多客户端身份验证插件在客户端将密码发送到服务器之前对密码进行哈希或加密。这使客户端可以避免以明文形式发送密码。
对于需要服务器接收客户端输入的密码的身份验证方案,无法进行哈希或加密。在这种情况下,将使用客户端端的mysql_clear_password插件,该插件使客户端可以将密码以明文形式发送到服务器。没有相应的服务器端插件。相反,mysql_clear_password可以与需要明文密码的任何服务器端插件一起在客户端端使用(例如 PAM 和简单的 LDAP 身份验证插件;请参见 Section 8.4.1.5, “PAM Pluggable Authentication”,以及 Section 8.4.1.7, “LDAP Pluggable Authentication”)。
下面的讨论提供了特定于明文插件身份验证的使用信息。有关 MySQL 中可插拔身份验证的一般信息,请参见 Section 8.2.17, “Pluggable Authentication”。
注意
在某些配置中,以明文形式发送密码可能会带来安全问题。为避免问题,如果存在密码可能被拦截的可能性,客户端应该使用一种保护密码的方法连接到 MySQL 服务器。可能的方法包括 SSL(请参见 Section 8.3, “Using Encrypted Connections”)、IPsec 或私有网络。
为了减少意外使用mysql_clear_password插件的可能性,MySQL 客户端必须显式启用它。可以通过几种方式实现:
-
将
LIBMYSQL_ENABLE_CLEARTEXT_PLUGIN环境变量设置为以1、Y或y开头的值。这将为所有客户端连接启用该插件。 -
mysql, mysqladmin, mysqlcheck, mysqldump, mysqlshow, 以及 mysqlslap 客户端程序支持
--enable-cleartext-plugin选项,可以在每次调用时启用该插件。 -
mysql_options()C API 函数支持MYSQL_ENABLE_CLEARTEXT_PLUGIN选项,可以在每个连接上启用该插件。此外,任何使用libmysqlclient并读取选项文件的程序都可以通过在客户端库读取的选项组中包含enable-cleartext-plugin选项来启用该插件。
原文:
dev.mysql.com/doc/refman/8.0/en/pam-pluggable-authentication.html
8.4.1.5 PAM 可插入认证
注意
PAM 可插入认证是 MySQL 企业版中包含的扩展,是一款商业产品。要了解更多关于商业产品的信息,请参阅www.mysql.com/products/。
MySQL 企业版支持一种认证方法,使得 MySQL 服务器能够使用 PAM(可插入认证模块)来认证 MySQL 用户。PAM 使得系统能够使用标准接口访问各种认证方法,例如传统的 Unix 密码或 LDAP 目录。
PAM 可插入认证提供了以下功能:
-
外部认证:PAM 认证使得 MySQL 服务器能够接受来自 MySQL 授权表之外定义的用户的连接,并使用 PAM 支持的方法进行认证。
-
代理用户支持:PAM 认证可以根据外部用户所属的 PAM 组和提供的认证字符串,返回一个与客户端程序传递的外部用户名不同的 MySQL 用户名,这意味着插件可以返回定义外部 PAM 认证用户应具有的特权的 MySQL 用户。例如,名为
joe的操作系统用户可以连接并具有名为developer的 MySQL 用户的权限。
PAM 可插入认证已在 Linux 和 macOS 上进行了测试;请注意 Windows 不支持 PAM。
以下表格显示了插件和库文件名称。文件名后缀可能在您的系统上有所不同。该文件必须位于由plugin_dir系统变量命名的目录中。有关安装信息,请参阅安装 PAM 可插入认证。
表 8.20 PAM 认证的插件和库名称
| 插件或文件 | 插件或文件名 |
|---|---|
| 服务器端插件 | authentication_pam |
| 客户端插件 | mysql_clear_password |
| 库文件 | authentication_pam.so |
与服务器端 PAM 插件通信的客户端mysql_clear_password明文插件内置于libmysqlclient客户端库中,并包含在所有发行版中,包括社区发行版。在所有 MySQL 发行版中包含客户端明文插件使得来自任何发行版的客户端都能连接到加载了服务器端 PAM 插件的服务器。
以下部分提供了特定于 PAM 可插入认证的安装和使用信息:
-
MySQL 用户 PAM 认证工作原理
-
安装 PAM 可插拔认证
-
卸载 PAM 可插拔认证
-
使用 PAM 可插拔认证
-
无代理用户的 PAM Unix 密码认证
-
无代理用户的 PAM LDAP 认证
-
带有代理用户和组映射的 PAM Unix 密码认证
-
访问 Unix 密码存储的 PAM 认证
-
PAM 认证调试
关于 MySQL 中可插拔认证的一般信息,请参见第 8.2.17 节,“可插拔认证”。关于mysql_clear_password插件的信息,请参见第 8.4.1.4 节,“客户端明文可插拔认证”。有关代理用户信息,请参见第 8.2.19 节,“代理用户”。
MySQL 用户的 PAM 认证工作原理
本节概述了 MySQL 和 PAM 如何共同工作来认证 MySQL 用户。有关如何设置 MySQL 帐户以使用特定 PAM 服务的示例,请参见使用 PAM 可插拔认证。
-
客户端程序和服务器进行通信,客户端向服务器发送客户端用户名(默认为操作系统用户名)和密码:
-
客户端用户名为外部用户名。
-
对于使用 PAM 服务器端认证插件的帐户,相应的客户端插件是
mysql_clear_password。这个客户端插件不执行密码哈希处理,结果客户端将密码以明文形式发送到服务器。
-
-
服务器根据客户端连接的外部用户名和主机找到匹配的 MySQL 帐户。PAM 插件使用 MySQL 服务器传递给它的信息(如用户名、主机名、密码和认证字符串)。当您定义一个使用 PAM 进行身份验证的 MySQL 帐户时,认证字符串包含:
-
PAM 服务名称,这是系统管理员可以用来引用特定应用程序的身份验证方法的名称。可以将多个应用程序关联到单个数据库服务器实例,因此服务名称的选择留给 SQL 应用程序开发人员。
-
可选地,如果要使用代理,可以从 PAM 组到 MySQL 用户名的映射。
-
-
该插件使用认证字符串中命名的 PAM 服务来检查用户凭据,并返回
'Authentication succeeded, Username is *user_name*'或'Authentication failed'。密码必须适用于 PAM 服务使用的密码存储。示例:-
对于传统的 Unix 密码,服务查找存储在
/etc/shadow文件中的密码。 -
对于 LDAP,服务查找存储在 LDAP 目录中的密码。
如果凭据检查失败,服务器将拒绝连接。
-
-
否则,认证字符串指示是否进行代理。如果字符串不包含 PAM 组映射,则不会进行代理。在这种情况下,MySQL 用户名与外部用户名相同。
-
否则,根据 PAM 组映射指示代理,MySQL 用户名根据映射列表中的第一个匹配组确定。“PAM 组”的含义取决于 PAM 服务。示例:
-
对于传统的 Unix 密码,组是在
/etc/group文件中定义的 Unix 组,可能在诸如/etc/security/group.conf之类的文件中补充了其他 PAM 信息。 -
对于 LDAP,组是在 LDAP 目录中定义的 LDAP 组。
如果代理用户(外部用户)对被代理的 MySQL 用户名具有
PROXY权限,则进行代理,代理用户承担被代理用户的权限。 -
安装 PAM 可插拔认证
本节描述了如何安装服务器端 PAM 认证插件。有关安装插件的一般信息,请参见第 7.6.1 节,“安装和卸载插件”。
要使服务器能够使用插件库文件,必须将其位于 MySQL 插件目录中(由plugin_dir系统变量命名的目录)。如果需要,通过在服务器启动时设置plugin_dir的值来配置插件目录位置。
插件库文件基本名称为authentication_pam,通常编译为.so后缀。
要在服务器启动时加载插件,请使用--plugin-load-add选项命名包含插件的库文件。使用此插件加载方法,每次启动服务器都必须提供该选项。例如,在服务器my.cnf文件中放入以下行:
[mysqld]
plugin-load-add=authentication_pam.so
修改my.cnf后,重新启动服务器以使新设置生效。
或者,要在运行时加载插件,请使用以下语句,根据需要调整.so后缀:
INSTALL PLUGIN authentication_pam SONAME 'authentication_pam.so';
INSTALL PLUGIN立即加载插件,并在mysql.plugins系统表中注册它,以使服务器在每次后续正常启动时加载它,而无需--plugin-load-add。
要验证插件安装,请检查信息模式PLUGINS表或使用SHOW PLUGINS语句(参见 Section 7.6.2, “Obtaining Server Plugin Information”)。例如:
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
FROM INFORMATION_SCHEMA.PLUGINS
WHERE PLUGIN_NAME LIKE '%pam%';
+--------------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+--------------------+---------------+
| authentication_pam | ACTIVE |
+--------------------+---------------+
如果插件初始化失败,请检查服务器错误日志以获取诊断信息。
要将 MySQL 帐户与 PAM 插件关联,请参阅使用 PAM 可插拔认证。
卸载 PAM 可插拔认证
卸载 PAM 认证插件的方法取决于您安装插件的方式:
-
如果您使用
--plugin-load-add选项在服务器启动时安装了插件,请在不带该选项的情况下重新启动服务器。 -
如果您使用
INSTALL PLUGIN语句在运行时安装了插件,则在服务器重新启动时仍保留安装。要卸载它,请使用UNINSTALL PLUGIN:UNINSTALL PLUGIN authentication_pam;
使用 PAM 可插拔认证
本节概述了如何使用 PAM 认证插件从 MySQL 客户端程序连接到服务器。以下各节提供了使用 PAM 认证的具体方法的说明。假定服务器正在运行并启用了服务器端 PAM 插件,如安装 PAM 可插拔认证中所述。
要在CREATE USER语句的IDENTIFIED WITH子句中引用 PAM 认证插件,请使用名称authentication_pam。例如:
CREATE USER *user*
IDENTIFIED WITH authentication_pam
AS '*auth_string*';
认证字符串指定以下类型的信息:
-
PAM 服务名称(参见 MySQL 用户的 PAM 认证工作原理)。以下讨论中的示例使用
mysql-unix作为服务名称,用于使用传统 Unix 密码进行身份验证,以及mysql-ldap用于使用 LDAP 进行身份验证。 -
对于代理支持,PAM 提供了一种方式,让 PAM 模块在连接到服务器时,返回一个与客户端程序传递的外部用户名不同的 MySQL 用户名。使用认证字符串来控制从外部用户名到 MySQL 用户名的映射。如果要利用代理用户功能,认证字符串必须包含这种映射。
例如,如果一个账户使用mysql-unix PAM 服务名称,并且应该将root和users PAM 组中的操作系统用户映射到developer和data_entry MySQL 用户,可以使用类似以下语句:
CREATE USER *user*
IDENTIFIED WITH authentication_pam
AS 'mysql-unix, root=developer, users=data_entry';
PAM 认证插件的认证字符串语法遵循以下规则:
-
该字符串由 PAM 服务名称组成,可选择地后跟一个 PAM 组映射列表,其中包含一个或多个关键字/值对,每个对指定一个 PAM 组名和一个 MySQL 用户名:
*pam_service_name*[,*pam_group_name*=*mysql_user_name*]...插件会解析每个使用该账户的连接尝试的认证字符串。为了最小化开销,尽量保持字符串尽可能短。
-
每个
*pam_group_name*=*mysql_user_name*对前面必须有一个逗号。 -
不在双引号内的前导和尾随空格会被忽略。
-
未引用的*
pam_service_name、pam_group_name和mysql_user_name*值可以包含除等号、逗号或空格之外的任何内容。 -
如果*
pam_service_name、pam_group_name或mysql_user_name*值用双引号引起来,引号之间的所有内容都是值的一部分。例如,如果值包含空格字符,则这是必要的。所有字符都是合法的,除了双引号和反斜杠(\)。要包含这两个字符,用反斜杠进行转义。
如果插件成功验证外部用户名(客户端传递的名称),它会查找认证字符串中的 PAM 组映射列表,并且如果存在,则根据外部用户所属的 PAM 组返回不同的 MySQL 用户名给 MySQL 服务器:
-
如果认证字符串不包含 PAM 组映射列表,则插件返回外部名称。
-
如果认证字符串包含 PAM 组映射列表,则插件会从左到右检查列表中的每个
*pam_group_name*=*mysql_user_name*对,并尝试在已认证用户分配的非 MySQL 目录中找到*pam_group_name值的匹配项,并返回找到的第一个匹配项的mysql_user_name*。如果插件找不到任何 PAM 组的匹配项,则返回外部名称。如果插件无法在目录中查找组,则会忽略 PAM 组映射列表并返回外部名称。
以下各节描述了如何设置使用 PAM 身份验证插件的几种身份验证方案:
-
没有代理用户。这仅使用 PAM 来检查登录名和密码。每个被允许连接到 MySQL 服务器的外部用户都应该有一个匹配的 MySQL 帐户,该帐户被定义为使用 PAM 身份验证。(为了使 MySQL 帐户
'*user_name*'@'*host_name*'与外部用户匹配,*user_name必须是外部用户名,host_name*必须与客户端连接的主机匹配。)认证可以通过各种 PAM 支持的方法进行。后续讨论将展示如何使用传统的 Unix 密码和 LDAP 密码来验证客户端凭据。PAM 身份验证,如果不通过代理用户或 PAM 组进行,需要 MySQL 用户名与操作系统用户名相同。 MySQL 用户名限制为 32 个字符(参见第 8.2.3 节,“授权表”),这限制了 PAM 非代理身份验证仅限于最多 32 个字符的 Unix 帐户。
-
仅代理用户,带有 PAM 组映射。对于这种情况,创建一个或多个定义不同权限集的 MySQL 帐户。(理想情况下,没有人应该直接使用这些帐户连接。)然后定义一个通过 PAM 进行身份验证的默认用户,使用某种映射方案(通常基于用户所属的外部 PAM 组)将所有外部用户名映射到持有权限集的少数 MySQL 帐户。任何连接并指定外部用户名作为客户端用户名的客户端都将映射到一个 MySQL 帐户并使用其权限。本讨论将展示如何使用传统的 Unix 密码设置此功能,但也可以使用其他 PAM 方法,如 LDAP。
这些方案的变体是可能的:
-
您可以允许一些用户直接登录(无需代理),但要求其他用户通过代理帐户连接。
-
您可以通过在 PAM 身份验证帐户之间使用不同的 PAM 服务名称,为一些用户使用一种 PAM 身份验证方法,为其他用户使用另一种方法。例如,您可以为一些用户使用
mysql-unixPAM 服务,为其他用户使用mysql-ldap。
示例做出以下假设。如果您的系统设置不同,您可能需要进行一些调整。
-
登录名和密码分别为
antonio和*antonio_password*。请将其更改为要进行身份验证的用户。 -
PAM 配置目录为
/etc/pam.d。 -
PAM 服务名称对应于认证方法(在本讨论中为
mysql-unix或mysql-ldap)。要使用给定的 PAM 服务,您必须在 PAM 配置目录中设置一个同名的 PAM 文件(如果不存在则创建该文件)。此外,您必须在使用该 PAM 服务进行认证的任何账户的CREATE USER语句的认证字符串中命名 PAM 服务。
PAM 认证插件在初始化时检查服务器启动环境中是否设置了AUTHENTICATION_PAM_LOG环境值。如果是,则插件会启用将诊断消息记录到标准输出的功能。根据服务器的启动方式,消息可能会显示在控制台上或错误日志中。这些消息对于调试描相关问题很有帮助。有关更多信息,请参阅 PAM 认证调试。
无代理用户的 PAM Unix 密码认证
这种认证场景使用 PAM 来检查以操作系统用户名和 Unix 密码定义的外部用户,而无需代理。每个被允许连接到 MySQL 服务器的外部用户都应该有一个匹配的 MySQL 账户,该账户被定义为通过传统的 Unix 密码存储使用 PAM 认证。
注意
传统的 Unix 密码是使用/etc/shadow文件进行检查的。有关与该文件相关的可能问题的信息,请参阅 PAM 认证访问 Unix 密码存储。
-
验证 Unix 认证是否允许使用用户名
antonio和密码*antonio_password*登录到操作系统。 -
通过创建名为
/etc/pam.d/mysql-unix的mysql-unixPAM 服务文件来设置 PAM 以使用传统的 Unix 密码对 MySQL 连接进行认证。文件内容取决于系统,因此请检查/etc/pam.d目录中现有的与登录相关的文件以查看其外观。在 Linux 上,mysql-unix文件可能如下所示:#%PAM-1.0 auth include password-auth account include password-auth对于 macOS,请使用
login而不是password-auth。在某些系统上,PAM 文件格式可能有所不同。例如,在 Ubuntu 和其他基于 Debian 的系统上,使用以下文件内容:
@include common-auth @include common-account @include common-session-noninteractive -
创建一个与操作系统用户名相同的 MySQL 账户,并定义其使用 PAM 插件和
mysql-unixPAM 服务进行认证:CREATE USER 'antonio'@'localhost' IDENTIFIED WITH authentication_pam AS 'mysql-unix'; GRANT ALL PRIVILEGES ON mydb.* TO 'antonio'@'localhost';在这里,认证字符串仅包含 PAM 服务名称,
mysql-unix,用于验证 Unix 密码。 -
使用mysql命令行客户端作为
antonio连接到 MySQL 服务器。例如:$> mysql --user=antonio --password --enable-cleartext-plugin Enter password: *antonio_password*服务器应允许连接,并且以下查询返回如下输出:
mysql> SELECT USER(), CURRENT_USER(), @@proxy_user; +-------------------+-------------------+--------------+ | USER() | CURRENT_USER() | @@proxy_user | +-------------------+-------------------+--------------+ | antonio@localhost | antonio@localhost | NULL | +-------------------+-------------------+--------------+这表明
antonio操作系统用户经过认证具有授予antonioMySQL 用户的权限,并且没有发生代理。
注意
客户端端的mysql_clear_password认证插件不会更改密码,因此客户端程序会将其以明文形式发送到 MySQL 服务器。这使得密码可以原样传递给 PAM。在某些配置中,明文密码是使用服务器端 PAM 库所必需的,但可能会存在安全问题。以下措施可最小化风险:
-
为了减少意外使用
mysql_clear_password插件的可能性,MySQL 客户端必须显式启用它(例如,使用--enable-cleartext-plugin选项)。参见 Section 8.4.1.4, “Client-Side Cleartext Pluggable Authentication”。 -
为了避免启用
mysql_clear_password插件时密码暴露,MySQL 客户端应该使用加密连接连接到 MySQL 服务器。参见 Section 8.3.1, “Configuring MySQL to Use Encrypted Connections”。
无代理用户的 PAM LDAP 认证
这种认证场景使用 PAM 来检查以操作系统用户名和 LDAP 密码定义的外部用户,而无需代理。每个被允许连接到 MySQL 服务器的外部用户都应该有一个匹配的 MySQL 账户,该账户被定义为通过 LDAP 进行 PAM 认证。
要使用 PAM LDAP 可插拔认证为 MySQL,必须满足以下先决条件:
-
PAM LDAP 服务必须与 LDAP 服务器通信。
-
每个要由 MySQL 进行认证的 LDAP 用户必须存在于由 LDAP 服务器管理的目录中。
注意
另一种使用 LDAP 进行 MySQL 用户认证的方法是使用特定于 LDAP 的认证插件。参见 Section 8.4.1.7, “LDAP Pluggable Authentication”。
配置 MySQL 以进行 PAM LDAP 认证如下:
-
验证 Unix 认证是否允许使用用户名
antonio和密码*antonio_password*登录到操作系统。 -
通过创建一个名为
/etc/pam.d/mysql-ldap的mysql-ldapPAM 服务文件来设置 PAM 以使用 LDAP 认证 MySQL 连接。文件内容取决于系统,因此请检查/etc/pam.d目录中现有的与登录相关的文件以查看其内容。在 Linux 上,mysql-ldap文件可能如下所示:#%PAM-1.0 auth required pam_ldap.so account required pam_ldap.so如果在您的系统上,PAM 对象文件的后缀与
.so不同,请替换正确的后缀。PAM 文件格式可能在某些系统上有所不同。
-
创建一个与操作系统用户名相同的 MySQL 账户,并定义其使用 PAM 插件和
mysql-ldapPAM 服务进行验证:CREATE USER 'antonio'@'localhost' IDENTIFIED WITH authentication_pam AS 'mysql-ldap'; GRANT ALL PRIVILEGES ON mydb.* TO 'antonio'@'localhost';这里,认证字符串仅包含 PAM 服务名称
mysql-ldap,用 LDAP 进行验证。 -
连接到服务器的方式与 PAM Unix 密码认证无代理用户中描述的相同。
使用代理用户和组映射的 PAM Unix 密码认证
此处描述的认证方案使用代理和 PAM 组映射,将使用 PAM 进行验证的连接 MySQL 用户映射到定义了不同权限集的其他 MySQL 账户上。用户不直接通过定义权限的账户连接。相反,他们通过使用 PAM 进行身份验证的默认代理账户连接,以便将所有外部用户映射到具有权限的 MySQL 账户。使用代理账户连接的任何用户都将映射到这些 MySQL 账户之一,其权限确定了允许外部用户执行的数据库操作。
此处所示的过程使用 Unix 密码认证。要改用 LDAP,请参阅 PAM LDAP 认证无代理用户的早期步骤。
注意
传统的 Unix 密码使用/etc/shadow文件进行检查。有关与该文件相关的可能问题的信息,请参阅 PAM 认证访问 Unix 密码存储。
-
验证 Unix 认证是否允许使用用户名
antonio和密码*antonio_password*登录操作系统。 -
验证
antonio是否是root或usersPAM 组的成员。 -
通过创建名为
/etc/pam.d/mysql-unix的文件,设置 PAM 通过操作系统用户验证mysql-unixPAM 服务。文件内容取决于系统,因此请查看/etc/pam.d目录中现有的与登录相关的文件以了解其内容。在 Linux 上,mysql-unix文件可能如下所示:#%PAM-1.0 auth include password-auth account include password-auth对于 macOS,请使用
login而不是password-auth。在某些系统上,PAM 文件格式可能有所不同。例如,在 Ubuntu 和其他基于 Debian 的系统上,使用以下文件内容:
@include common-auth @include common-account @include common-session-noninteractive -
创建一个默认的代理用户(
''@''),将外部 PAM 用户映射到代理账户:CREATE USER ''@'' IDENTIFIED WITH authentication_pam AS 'mysql-unix, root=developer, users=data_entry';这里,认证字符串包含了 PAM 服务名称
mysql-unix,用于验证 Unix 密码。认证字符串还将root和usersPAM 组中的外部用户映射到developer和data_entryMySQL 用户名。在设置代理用户时,必须在 PAM 服务名称后面提供 PAM 组映射列表。否则,插件无法确定如何将外部用户名映射到正确的被代理 MySQL 用户名。
注意
如果您的 MySQL 安装中存在匿名用户,则可能会与默认代理用户发生冲突。有关此问题的更多信息以及处理方法,请参见 Default Proxy User and Anonymous User Conflicts。
-
创建被代理账户并为每个账户授予应具有的权限:
CREATE USER 'developer'@'localhost' IDENTIFIED WITH mysql_no_login; CREATE USER 'data_entry'@'localhost' IDENTIFIED WITH mysql_no_login; GRANT ALL PRIVILEGES ON mydevdb.* TO 'developer'@'localhost'; GRANT ALL PRIVILEGES ON mydb.* TO 'data_entry'@'localhost';代理账户使用
mysql_no_login认证插件,以防止客户端直接使用这些账户登录到 MySQL 服务器。相反,使用 PAM 进行身份验证的用户应该通过代理使用基于他们的 PAM 组的developer或data_entry账户。(假设插件已安装。有关说明,请参见 Section 8.4.1.9, “No-Login Pluggable Authentication”。)有关保护代理账户免受直接使用的替代方法,请参见 Preventing Direct Login to Proxied Accounts。 -
为每个被代理账户授予
PROXY权限:GRANT PROXY ON 'developer'@'localhost' TO ''@''; GRANT PROXY ON 'data_entry'@'localhost' TO ''@''; -
使用mysql命令行客户端作为
安东尼奥连接到 MySQL 服务器。$> mysql --user=antonio --password --enable-cleartext-plugin Enter password: *antonio_password*服务器使用默认的
''@''代理账户对连接进行身份验证。安东尼奥的权限取决于他是哪些 PAM 组的成员。如果安东尼奥是rootPAM 组的成员,PAM 插件将root映射到developerMySQL 用户名并将该名称返回给服务器。服务器验证''@''是否具有developer的PROXY权限,并允许连接。以下查询返回如下输出:mysql> SELECT USER(), CURRENT_USER(), @@proxy_user; +-------------------+---------------------+--------------+ | USER() | CURRENT_USER() | @@proxy_user | +-------------------+---------------------+--------------+ | antonio@localhost | developer@localhost | ''@'' | +-------------------+---------------------+--------------+这表明
安东尼奥操作系统用户被验证具有授予developerMySQL 用户的权限,并且通过默认代理账户进行代理。如果
安东尼奥不是rootPAM 组的成员,但是usersPAM 组的成员,类似的过程会发生,但插件将userPAM 组成员映射到data_entryMySQL 用户名并将该名称返回给服务器:mysql> SELECT USER(), CURRENT_USER(), @@proxy_user; +-------------------+----------------------+--------------+ | USER() | CURRENT_USER() | @@proxy_user | +-------------------+----------------------+--------------+ | antonio@localhost | data_entry@localhost | ''@'' | +-------------------+----------------------+--------------+这表明
安东尼奥操作系统用户被验证具有data_entryMySQL 用户的权限,并且通过默认代理账户进行代理。
注意
客户端端的mysql_clear_password认证插件保持密码不变,因此客户端程序将其以明文形式发送到 MySQL 服务器。这使得密码可以原样传递给 PAM。在某些配置中,明文密码是使用服务器端 PAM 库所必需的,但可能在某些配置中存在安全问题。以下措施可最小化风险:
-
为了减少意外使用
mysql_clear_password插件的可能性,MySQL 客户端必须显式启用它(例如,使用--enable-cleartext-plugin选项)。参见 Section 8.4.1.4, “Client-Side Cleartext Pluggable Authentication”。 -
启用
mysql_clear_password插件以避免密码暴露,MySQL 客户端应该使用加密连接连接到 MySQL 服务器。参见 Section 8.3.1, “Configuring MySQL to Use Encrypted Connections”。
PAM 身份验证访问 Unix 密码存储
在某些系统上,Unix 身份验证使用密码存储,例如/etc/shadow,这是一个通常具有受限访问权限的文件。这可能导致 MySQL 基于 PAM 的身份验证失败。不幸的是,PAM 实现不允许区分“密码无法检查”(例如,由于无法读取/etc/shadow)和“密码不匹配”。如果您正在使用 Unix 密码存储进行 PAM 身份验证,您可以通过以下方法之一启用 MySQL 对其的访问:
-
假设 MySQL 服务器是从
mysql操作系统帐户运行的,请将该帐户放入具有/etc/shadow访问权限的shadow组中:-
在
/etc/group中创建���个shadow组。 -
将
mysql操作系统用户添加到/etc/group中的shadow组。 -
将
/etc/group分配给shadow组并启用组读权限:chgrp shadow /etc/shadow chmod g+r /etc/shadow -
重新启动 MySQL 服务器。
-
-
如果您正在使用
pam_unix模块和unix_chkpwd实用程序,请按以下方式启用密码存储访问:chmod u-s /usr/sbin/unix_chkpwd setcap cap_dac_read_search+ep /usr/sbin/unix_chkpwd根据您的平台调整unix_chkpwd的路径。
PAM 身份验证调试
PAM 身份验证插件在初始化时检查AUTHENTICATION_PAM_LOG环境值是否已设置。在 MySQL 8.0.35 及更早版本中,该值无关紧要。如果是,则插件将启用将诊断消息记录到标准输出的功能。这些消息可能有助于调试插件执行身份验证时出现的与 PAM 相关的问题。您应该知道,在这些版本中,这些消息中包含密码。
从 MySQL 8.0.36 开始,设置AUTHENTICATION_PAM_LOG=1(或其他任意值)会产生相同的诊断消息,但不包含任何密码。如果您希望在这些消息中包含密码,请设置AUTHENTICATION_PAM_LOG=PAM_LOG_WITH_SECRET_INFO。
一些消息包含对 PAM 插件源文件和行号的引用,这使得插件操作与其发生的代码位置更紧密地联系在一起。
用于调试连接失败并确定连接尝试期间发生的情况的另一种技术是配置 PAM 认证以允许所有连接,然后检查系统日志文件。这种技术应仅在临时基础上使用,而不是在生产服务器上使用。
使用以下内容配置名为 /etc/pam.d/mysql-any-password 的 PAM 服务文件(在某些系统上格式可能有所不同):
#%PAM-1.0
auth required pam_permit.so
account required pam_permit.so
创建一个使用 PAM 插件并命名为 mysql-any-password PAM 服务的帐户:
CREATE USER 'testuser'@'localhost'
IDENTIFIED WITH authentication_pam
AS 'mysql-any-password';
mysql-any-password 服务文件会导致任何身份验证尝试返回 true,即使密码不正确。如果身份验证尝试失败,这说明配置问题在 MySQL 方面。否则,问题在操作系统/PAM 方面。要查看可能发生的情况,请检查系统日志文件,如 /var/log/secure、/var/log/audit.log、/var/log/syslog 或 /var/log/messages。
确定问题后,删除 mysql-any-password PAM 服务文件以禁用任意密码访问。
原文:
dev.mysql.com/doc/refman/8.0/en/windows-pluggable-authentication.html
8.4.1.6 Windows 可插拔认证
注意
Windows 可插拔认证是 MySQL 企业版中包含的扩展,这是一个商业产品。要了解更多关于商业产品的信息,请查看www.mysql.com/products/。
Windows 版 MySQL 企业版支持一种在 Windows 上执行外部认证的认证方法,使 MySQL 服务器能够使用本机 Windows 服务对客户端连接进行认证。已登录到 Windows 的用户可以根据其环境中的信息从 MySQL 客户端程序连接到服务器,而无需指定额外的密码。
客户端和服务器在认证握手中交换数据包。由于这种交换,服务器创建一个代表客户端在 Windows OS 中身份的安全上下文对象。这个身份包括客户端账户的名称。Windows 可插拔认证使用客户端的身份来检查它是否是给定账户或组的成员。默认情况下,协商使用 Kerberos 进行认证,如果 Kerberos 不可用,则使用 NTLM。
Windows 可插拔认证提供了以下功能:
-
外部认证:Windows 认证使 MySQL 服务器能够接受来自在 Windows 登录的 MySQL 授权表之外定义的用户的连接。
-
代理用户支持:Windows 认证可以将一个与客户端程序传递的外部用户名不同的用户名返回给 MySQL。这意味着插件可以返回定义外部 Windows 认证用户应具有的权限的 MySQL 用户。例如,一个名为
joe的 Windows 用户可以连接并具有名为developer的 MySQL 用户的权限。
以下表格显示了插件和库文件的名称。文件必须位于由plugin_dir系统变量命名的目录中。
表 8.21 Windows 认证的插件和库名称
| 插件或文件 | 插件或文件名 |
|---|---|
| 服务器端插件 | authentication_windows |
| 客户端插件 | authentication_windows_client |
| 库文件 | authentication_windows.dll |
库文件仅包含服务器端插件。客户端插件内置于libmysqlclient客户端库中。
服务器端 Windows 认证插件仅包含在 MySQL 企业版中。它不包含在 MySQL 社区发行版中。客户端插件包含在所有发行版中,包括社区发行版。这使得来自任何发行版的客户端都能连接到加载了服务器端插件的服务器。
以下部分提供了特定于 Windows 可插拔认证的安装和使用信息:
-
安装 Windows 可插拔认证
-
卸载 Windows 可插拔认证
-
使用 Windows 可插拔认证
有关 MySQL 中可插拔认证的一般信息,请参阅 Section 8.2.17, “Pluggable Authentication”。有关代理用户信息,请参阅 Section 8.2.19, “Proxy Users”。
安装 Windows 可插拔认证
本节描述了如何安装服务器端 Windows 认证插件。有关安装插件的一般信息,请参阅 Section 7.6.1, “Installing and Uninstalling Plugins”。
要被服务器使用,插件库文件必须位于 MySQL 插件目录中(由plugin_dir系统变量命名的目录)。如果需要,通过在服务器启动时设置plugin_dir的值来配置插件目录位置。
要在服务器启动时加载插件,请使用--plugin-load-add选项命名包含插件的库文件。使用此插件加载方法,每次服务器启动时都必须提供该选项。例如,将以下行放入服务器my.cnf文件中:
[mysqld]
plugin-load-add=authentication_windows.dll
修改my.cnf后,重新启动服务器以使新设置生效。
或者,要在运行时加载插件,请使用以下语句:
INSTALL PLUGIN authentication_windows SONAME 'authentication_windows.dll';
INSTALL PLUGIN立即加载插件,并在mysql.plugins系统表中注册它,以使服务器在每次后续正常启动时加载它,而无需--plugin-load-add。
要验证插件安装,请检查信息模式PLUGINS表,或使用SHOW PLUGINS语句(参见 Section 7.6.2, “Obtaining Server Plugin Information”)。例如:
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
FROM INFORMATION_SCHEMA.PLUGINS
WHERE PLUGIN_NAME LIKE '%windows%';
+------------------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+------------------------+---------------+
| authentication_windows | ACTIVE |
+------------------------+---------------+
如果插件初始化失败,请检查服务器错误日志以获取诊断消息。
要将 MySQL 帐户与 Windows 认证插件关联,请参阅使用 Windows 可插拔认证。 通过authentication_windows_use_principal_name和authentication_windows_log_level系统变量提供了额外的插件控制。 请参阅第 7.1.8 节,“服务器系统变量”。
卸载 Windows 可插拔认证
卸载 Windows 认证插件的方法取决于您安装它的方式:
-
如果您在服务器启动时使用
--plugin-load-add选项安装插件,请在不带该选项的情况下重新启动服务器。 -
如果您使用
INSTALL PLUGIN语句在运行时安装插件,则插件将在服务器重新启动时保持安装状态。 要卸载它,请使用UNINSTALL PLUGIN:UNINSTALL PLUGIN authentication_windows;
另外,删除任何设置 Windows 插件相关系统变量的启动选项。
使用 Windows 可插拔认证
Windows 认证插件支持使用 MySQL 帐户,使得已登录 Windows 的用户可以连接到 MySQL 服务器,而无需指定额外的密码。 假定服务器正在运行并启用了服务器端插件,如安装 Windows 可插拔认证中所述。 一旦 DBA 启用了服务器端插件并设置了要使用它的帐户,客户端就可以使用这些帐户连接,而无需进行其他设置。
在CREATE USER语句的IDENTIFIED WITH子句中引用 Windows 认证插件,请使用名称authentication_windows。 假设 Windows 用户Rafal和Tasha应被允许连接到 MySQL,以及Administrators或Power Users组中的任何用户。 要设置这一点,请创建一个名为sql_admin的 MySQL 帐户,该帐户使用 Windows 插件进行身份验证:
CREATE USER sql_admin
IDENTIFIED WITH authentication_windows
AS 'Rafal, Tasha, Administrators, "Power Users"';
插件名称为authentication_windows。 AS关键字后面的字符串是认证字符串。 它指定了名为Rafal或Tasha的 Windows 用户被允许作为 MySQL 用户sql_admin进行服务器身份验证,以及Administrators或Power Users组中的任何 Windows 用户。 后一个组名包含一个空格,因此必须用双引号括起来。
创建sql_admin账户后,已登录到 Windows 的用户可以尝试使用该账户连接到服务器:
C:\> mysql --user=sql_admin
这里不需要密码。authentication_windows插件使用 Windows 安全 API 来检查连接的是哪个 Windows 用户。如果该用户名为Rafal或Tasha,或者是Administrators或Power Users组的成员,则服务器授予访问权限,并将客户端验证为sql_admin,并具有授予sql_admin账户的任何权限。否则,服务器将拒绝访问。
Windows 认证插件的认证字符串语法遵循以下规则:
-
该字符串由一个或多个以逗号分隔的用户映射组成。
-
每个用户映射将 Windows 用户或组名与 MySQL 用户名称关联起来:
*win_user_or_group_name=mysql_user_name* *win_user_or_group_name*对于后一种语法,如果没有给出*
mysql_user_name*值,则隐式值是由CREATE USER语句创建的 MySQL 用户。因此,以下语句是等效的:CREATE USER sql_admin IDENTIFIED WITH authentication_windows AS 'Rafal, Tasha, Administrators, "Power Users"'; CREATE USER sql_admin IDENTIFIED WITH authentication_windows AS 'Rafal=sql_admin, Tasha=sql_admin, Administrators=sql_admin, "Power Users"=sql_admin'; -
值中的每个反斜杠字符(
\)都必须加倍,因为反斜杠是 MySQL 字符串中的转义字符。 -
在双引号内部的前导和尾随空格将被忽略。
-
未引用的*
win_user_or_group_name和mysql_user_name*值可以包含除等号、逗号或空格之外的任何内容。 -
如果*
win_user_or_group_name和/或mysql_user_name*值用双引号引起来,那么引号之间的所有内容都是值的一部分。例如,如果名称包含空格字符,则这是必要的。双引号内的所有字符都是合法的,除了双引号和反斜杠。要包含这两个字符,需要用反斜杠进行转义。 -
*
win_user_or_group_name*值使用 Windows 主体的传统语法,可以是本地的或域中的。示例(注意反斜杠的加倍):domain\\user .\\user domain\\group .\\group BUILTIN\\WellKnownGroup
当服务器调用插件来验证客户端时,插件从左到右扫描认证字符串,以查找与 Windows 用户匹配的用户或组。如果有匹配,插件将相应的*mysql_user_name*返回给 MySQL 服务器。如果没有匹配,则认证失败。
用户名称匹配优先于组名称匹配。假设名为win_user的 Windows 用户是win_group的成员,并且认证字符串如下所示:
'win_group = sql_user1, win_user = sql_user2'
当win_user连接到 MySQL 服务器时,既与win_group匹配,也与win_user匹配。插件将用户验证为sql_user2,因为更具体的用户匹配优先于组匹配,即使组在认证字符串中首先列出。
Windows 身份验证始终适用于从运行服务器的同一台计算机发起的连接。对于跨计算机连接,两台计算机必须在 Microsoft Active Directory 中注册。如果它们在同一个 Windows 域中,则无需指定域名。也可以允许来自不同域的连接,就像这个例子中一样:
CREATE USER sql_accounting
IDENTIFIED WITH authentication_windows
AS 'SomeDomain\\Accounting';
这里 SomeDomain 是另一个域的名称。反斜杠字符被加倍,因为它是字符串中的 MySQL 转义字符。
MySQL 支持代理用户的概念,即客户端可以使用一个账户连接和认证到 MySQL 服务器,但在连接时具有另一个账户的权限(参见 Section 8.2.19, “Proxy Users”)。假设您希望 Windows 用户使用单个用户名连接,但根据其 Windows 用户和组名称映射到特定的 MySQL 账户,如下所示:
-
local_user和MyDomain\domain_user本地和域 Windows 用户应映射到local_wladMySQL 账户。 -
MyDomain\Developers域组中的用户应映射到local_devMySQL 账户。 -
本地机器管理员应映射到
local_adminMySQL 账户。
要设置这个,为 Windows 用户创建一个代理账户进行连接,并配置此账户,使用户和组映射到适当的 MySQL 账户(local_wlad、local_dev、local_admin)。此外,授予 MySQL 账户执行所需操作的适当权限。以下说明使用 win_proxy 作为代理账户,local_wlad、local_dev 和 local_admin 作为代理账户。
-
创建代理 MySQL 账户:
CREATE USER win_proxy IDENTIFIED WITH authentication_windows AS 'local_user = local_wlad, MyDomain\\domain_user = local_wlad, MyDomain\\Developers = local_dev, BUILTIN\\Administrators = local_admin'; -
为了使代理工作,代理账户必须存在,因此创建它们:
CREATE USER local_wlad IDENTIFIED WITH mysql_no_login; CREATE USER local_dev IDENTIFIED WITH mysql_no_login; CREATE USER local_admin IDENTIFIED WITH mysql_no_login;代理账户使用
mysql_no_login认证插件,以防止客户端直接使用这些账户登录到 MySQL 服务器。相反,使用 Windows 进行身份验证的用户应该使用win_proxy代理账户。(这假定插件已安装。有关说明,请参见 Section 8.4.1.9, “No-Login Pluggable Authentication”。)有关保护代理账户免受直接使用的替代方法,请参见 Preventing Direct Login to Proxied Accounts。您还应该执行
GRANT语句(未显示),为每个代理账户授予所需的 MySQL 访问权限。 -
为代理账户授予
PROXY权限,以代表每个代理账户:GRANT PROXY ON local_wlad TO win_proxy; GRANT PROXY ON local_dev TO win_proxy; GRANT PROXY ON local_admin TO win_proxy;
现在,Windows 用户local_user和MyDomain\domain_user可以作为win_proxy连接到 MySQL 服务器,并在经过身份验证后具有身份验证字符串中指定帐户(在本例中为local_wlad)的权限。以win_proxy身份连接的MyDomain\Developers组中的用户具有local_dev帐户的权限。BUILTIN\Administrators组中的用户具有local_admin帐户的权限。
要配置身份验证,使所有没有自己的 MySQL 帐户的 Windows 用户通过代理帐户进行身份验证,请在上述说明中将默认代理帐户(''@'')替换为win_proxy。有关默认代理帐户的信息,请参阅 Section 8.2.19, “Proxy Users”。
注意
如果您的 MySQL 安装中存在匿名用户,则它们可能与默认代理用户发生冲突。有关此问题的更多信息以及处理方法,请参阅 Default Proxy User and Anonymous User Conflicts。
要在 Connector/NET 8.0 及更高版本中使用 Windows 身份验证插件与 Connector/NET 连接字符串,请参阅 Connector/NET Authentication。
原文:
dev.mysql.com/doc/refman/8.0/en/ldap-pluggable-authentication.html
8.4.1.7 LDAP 可插拔身份验证
注意
LDAP 可插拔身份验证是 MySQL 企业版中包含的扩展,是一种商业产品。要了解更多关于商业产品的信息,请参见www.mysql.com/products/。
MySQL 企业版支持一种身份验证方法,使 MySQL 服务器能够使用 LDAP(轻量级目录访问协议)通过访问目录服务(如 X.500)对 MySQL 用户进行身份验证。MySQL 使用 LDAP 获取用户、凭据和组信息。
LDAP 可插拔身份验证提供以下功能:
-
外部身份验证:LDAP 身份验证使 MySQL 服务器能够接受来自 LDAP 目录中定义的用户的连接,而不是在 MySQL 授权表中定义的用户。
-
代理用户支持:LDAP 身份验证可以根据外部用户所属的 LDAP 组返回一个与客户端程序传递的外部用户名不同的 MySQL 用户名给 MySQL,这意味着 LDAP 插件可以返回定义外部 LDAP 身份验证用户应具有的特权的 MySQL 用户。例如,名为
joe的 LDAP 用户可以连接并具有名为developer的 MySQL 用户的特权,如果joe的 LDAP 组是developer。 -
安全性:使用 TLS,连接到 LDAP 服务器可以是安全的。
服务器端和客户端插件可用于简单和基于 SASL 的 LDAP 身份验证。在 Microsoft Windows 上,不支持基于 SASL 的 LDAP 身份验证的服务器端插件,但支持客户端插件。
以下表格显示了简单和基于 SASL 的 LDAP 身份验证的插件和库文件名称。文件名后缀可能在您的系统上有所不同。这些文件必须位于由plugin_dir系统变量指定的目录中。
表 8.22 简单 LDAP 身份验证的插件和库名称
| 插件或文件 | 插件或文件名称 |
|---|---|
| 服务器端插件名称 | authentication_ldap_simple |
| 客户端插件名称 | mysql_clear_password |
| 库文件名称 | authentication_ldap_simple.so |
表 8.23 基于 SASL 的 LDAP 身份验证的插件和库名称
| 插件或文件 | 插件或文件名称 |
|---|---|
| 服务器端插件名称 | authentication_ldap_sasl |
| 客户端插件名称 | authentication_ldap_sasl_client |
| 库文件名称 | authentication_ldap_sasl.so,authentication_ldap_sasl_client.so |
库文件仅包含authentication_ldap_*XXX*身份验证插件。客户端mysql_clear_password插件内置于libmysqlclient客户端库中。
每个服务器端 LDAP 插件与特定的客户端插件配合使用:
-
服务器端的
authentication_ldap_simple插件执行简单的 LDAP 认证。对于使用此插件的帐户连接,客户端程序使用客户端的mysql_clear_password插件,该插件将密码以明文形式发送到服务器。不使用密码哈希或加密,因此建议在 MySQL 客户端和服务器之间建立安全连接,以防止密码泄露。 -
服务器端的
authentication_ldap_sasl插件执行基于 SASL 的 LDAP 认证。对于使用此插件的帐户连接,客户端程序使用客户端的authentication_ldap_sasl_client插件。客户端端和服务器端的 SASL LDAP 插件使用 SASL 消息来在 LDAP 协议中安全传输凭据,以避免在 MySQL 客户端和服务器之间发送明文密码。注意
在 Microsoft Windows 上,不支持基于 SASL 的 LDAP 认证的服务器插件,但支持客户端插件。在其他平台上,服务器和客户端插件都受支持。
服务器端的 LDAP 认证插件仅包含在 MySQL 企业版中。它们不包含在 MySQL 社区发行版中。客户端端的 SASL LDAP 插件包含在所有发行版中,包括社区发行版,并且如前所述,客户端的mysql_clear_password插件内置于libmysqlclient客户端库中,该库也包含在所有发行版中。这使得来自任何发行版的客户端都可以连接到加载了适当服务器端插件的服务器。
以下各节提供了特定于 LDAP 可插拔认证的安装和使用信息:
-
LDAP 可插拔认证的先决条件
-
MySQL 用户的 LDAP 认证工作原理
-
安装 LDAP 可插拔认证
-
卸载 LDAP 可插拔认证
-
LDAP 可插拔认证和 ldap.conf
-
使用 LDAP 可插拔认证
-
简单 LDAP 认证
-
基于 SASL 的 LDAP 认证
-
代理 LDAP 认证
-
LDAP 认证组偏好和映射规范
-
LDAP 认证用户 DN 后缀
-
LDAP 认证方法
-
GSSAPI/Kerberos 认证方法
-
LDAP 搜索引荐
有关 MySQL 中可插拔认证的一般信息,请参见第 8.2.17 节,“可插拔认证”。有关mysql_clear_password插件的信息,请参见第 8.4.1.4 节,“客户端明文可插拔认证”。有关代理用户信息,请参见第 8.2.19 节,“代理用户”。
注意
如果您的系统支持 PAM 并允许 LDAP 作为 PAM 认证方法,另一种使用 LDAP 进行 MySQL 用户认证的方法是使用服务器端authentication_pam插件。请参见第 8.4.1.5 节,“PAM 可插拔认证”。
LDAP 可插拔认证的先决条件
要为 MySQL 使用 LDAP 可插拔认证,必须满足以下先决条件:
-
必须有 LDAP 服务器可用,以便 LDAP 认证插件与之通信。
-
要由 MySQL 进行认证的 LDAP 用户必须存在于 LDAP 服务器管理的目录中。
-
在使用服务器端
authentication_ldap_sasl或authentication_ldap_simple插件的系统上必须有 LDAP 客户端库可用。目前支持的库是 Windows 本机 LDAP 库,或非 Windows 系统上的 OpenLDAP 库。 -
要使用基于 SASL 的 LDAP 认证:
-
LDAP 服务器必须配置为与 SASL 服务器通信。
-
在使用客户端端
authentication_ldap_sasl_client插件的系统上必须有 SASL 客户端库可用。目前,唯一支持的库是 Cyrus SASL 库。 -
要使用特定的 SASL 认证方法,必须提供该方法所需的任何其他服务。例如,要使用 GSSAPI/Kerberos,必须提供 GSSAPI 库和 Kerberos 服务。
-
MySQL 用户的 LDAP 认证工作原理
本节概述了 MySQL 和 LDAP 如何共同工作以对 MySQL 用户进行认证。有关如何设置 MySQL 账户以使用特定 LDAP 认证插件的示例,请参见使用 LDAP 可插拔认证。有关 LDAP 插件可用的认证方法的信息,请参见 LDAP 认证方法。
客户端连接到 MySQL 服务器,提供 MySQL 客户端用户名和密码:
-
对于简单的 LDAP 认证,客户端和服务器端插件以明文形式传输密码。建议在 MySQL 客户端和服务器之间建立安全连接,以防止密码泄露。
-
对于基于 SASL 的 LDAP 认证,客户端和服务器端插件避免在 MySQL 客户端和服务器之间发送明文密码。例如,插件可能使用 SASL 消息来在 LDAP 协议内安全传输凭据。对于 GSSAPI 认证方法,客户端和服务器端插件使用 Kerberos 进行安全通信,而不直接使用 LDAP 消息。
如果客户端用户名和主机名与任何 MySQL 账户不匹配,则连接将被拒绝。
如果存在匹配的 MySQL 账户,则进行 LDAP 认证。LDAP 服务器查找与用户匹配的条目,并根据 LDAP 密码对该条目进行认证:
-
如果 MySQL 账户指定了 LDAP 用户的区分名称(DN),则 LDAP 认证将使用该值和客户端提供的 LDAP 密码。(要将 LDAP 用户 DN 与 MySQL 账户关联,包括在创建账户的
CREATE USER语句中指定认证字符串的BY子句。) -
如果 MySQL 账户名称不是 LDAP 用户 DN,则 LDAP 认证使用客户端提供的用户名和 LDAP 密码。在这种情况下,认证插件首先使用根 DN 和密码作为凭据绑定到 LDAP 服务器,以根据客户端用户名找到用户 DN,然后根据 LDAP 密码对该用户 DN 进行认证。如果根凭据的绑定失败,说明根 DN 和密码设置为不正确的值,或为空(未设置),且 LDAP 服务器不允许匿名连接。
如果 LDAP 服务器找不到匹配项或找到多个匹配项,则认证失败,客户端连接将被拒绝。
如果 LDAP 服务器找到单个匹配项,则 LDAP 认证成功(假设密码正确),LDAP 服务器返回 LDAP 条目,认证插件根据该条目确定经过认证的用户名称:
-
如果 LDAP 条目具有组属性(默认为
cn属性),插件将其值作为经过认证的用户名返回。 -
如果 LDAP 条目没有组属性,认证插件将返回客户端用户名作为经过认证的用户名。
MySQL 服务器将客户端用户名与经过认证的用户名进行比较,以确定客户端会话是否发生代理:
-
如果名称相同,则不会发生代理:将用于权限检查的与客户端用户名匹配的 MySQL 帐户。
-
如果名称不同,将发生代理:MySQL 将寻找与经过认证的用户名匹配的帐户。该帐户将成为代理用户,用于权限检查。与客户端用户名匹配的 MySQL 帐户将被视为外部代理用户。
安装 LDAP 可插入认证
本节描述了如何安装服务器端 LDAP 认证插件。有关安装插件的一般信息,请参见第 7.6.1 节,“安装和卸载插件”。
要被服务器使用,插件库文件必须位于 MySQL 插件目录中(由plugin_dir系统变量命名的目录)。如有必要,通过在服务器启动时设置plugin_dir的值来配置插件目录位置。
服务器端插件库文件的基本名称为authentication_ldap_simple和authentication_ldap_sasl。文件名后缀因平台而异(例如,对于 Unix 和类 Unix 系统,为.so,对于 Windows 为.dll)。
注意
在 Microsoft Windows 上,不支持基于 SASL 的 LDAP 认证的服务器插件,但支持客户端插件。在其他平台上,服务器和客户端插件都受支持。
要在服务器启动时加载插件,使用--plugin-load-add选项命名包含插件的库文件。使用此插件加载方法,选项必须在每次服务器启动时给出。还要为您希望配置的任何插件提供的系统变量指定值。
每个服务器端 LDAP 插件都公开一组系统变量,以使其操作可以配置。设置大多数这些变量是可选的,但您必须设置指定 LDAP 服务器主机(以便插件知道在哪里连接)和 LDAP 绑定操作的基本区分名称(以限制搜索范围并获得更快的搜索)的变量。有关所有 LDAP 系统变量的详细信息,请参见第 8.4.1.13 节,“可插入认证系统变量”。
要加载插件并设置 LDAP 服务器主机和 LDAP 绑定操作的基本区分名称,需要在您的my.cnf文件中添加类似以下的行,根据需要调整.so后缀以适应您的平台:
[mysqld]
plugin-load-add=authentication_ldap_simple.so
authentication_ldap_simple_server_host=127.0.0.1
authentication_ldap_simple_bind_base_dn="dc=example,dc=com"
plugin-load-add=authentication_ldap_sasl.so
authentication_ldap_sasl_server_host=127.0.0.1
authentication_ldap_sasl_bind_base_dn="dc=example,dc=com"
修改my.cnf后,重新启动服务器以使新设置生效。
或者,要在运行时加载插件,请使用以下语句,根据需要调整您平台的.so后缀:
INSTALL PLUGIN authentication_ldap_simple
SONAME 'authentication_ldap_simple.so';
INSTALL PLUGIN authentication_ldap_sasl
SONAME 'authentication_ldap_sasl.so';
INSTALL PLUGIN立即加载插件,并在mysql.plugins系统表中注册它,以使服务器在每次后续正常启动时加载它,而无需--plugin-load-add。
在运行时安装插件后,它们公开的系统变量变得可用,您可以将其设置添加到您的my.cnf文件中,以配置插件以供后续重新启动。例如:
[mysqld]
authentication_ldap_simple_server_host=127.0.0.1
authentication_ldap_simple_bind_base_dn="dc=example,dc=com"
authentication_ldap_sasl_server_host=127.0.0.1
authentication_ldap_sasl_bind_base_dn="dc=example,dc=com"
修改my.cnf后,重新启动服务器以使新设置生效。
要在运行时设置和持久化每个值,而不是在启动时,请使用以下语句:
SET PERSIST authentication_ldap_simple_server_host='127.0.0.1';
SET PERSIST authentication_ldap_simple_bind_base_dn='dc=example,dc=com';
SET PERSIST authentication_ldap_sasl_server_host='127.0.0.1';
SET PERSIST authentication_ldap_sasl_bind_base_dn='dc=example,dc=com';
SET PERSIST为运行中的 MySQL 实例设置一个值。它还保存该值,导致其在后续服务器重新启动时保留。要更改运行中的 MySQL 实例的值,而不使其在后续重新启动时保留,请使用GLOBAL关键字而不是PERSIST。参见 Section 15.7.6.1, “SET Syntax for Variable Assignment”。
要验证插件安装,请检查信息模式PLUGINS表或使用SHOW PLUGINS语句(参见 Section 7.6.2, “Obtaining Server Plugin Information”)。例如:
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
FROM INFORMATION_SCHEMA.PLUGINS
WHERE PLUGIN_NAME LIKE '%ldap%';
+----------------------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+----------------------------+---------------+
| authentication_ldap_sasl | ACTIVE |
| authentication_ldap_simple | ACTIVE |
+----------------------------+---------------+
如果插件初始化失败,请检查服务器错误日志以获取诊断消息。
要将 MySQL 帐户与 LDAP 插件关联,请参阅使用 LDAP 可插拔认证。
SELinux 的附加说明
在运行 EL6 或启用 SELinux 的 EL 系统上,需要更改 SELinux 策略以启用 MySQL LDAP 插件与 LDAP 服务通信:
-
创建一个包含以下内容的文件
mysqlldap.te:module mysqlldap 1.0; require { type ldap_port_t; type mysqld_t; class tcp_socket name_connect; } #============= mysqld_t ============== allow mysqld_t ldap_port_t:tcp_socket name_connect; -
将安全策略模块编译为二进制表示:
checkmodule -M -m mysqlldap.te -o mysqlldap.mod -
创建一个 SELinux 策略模块包:
semodule_package -m mysqlldap.mod -o mysqlldap.pp -
安装模块包:
semodule -i mysqlldap.pp -
当 SELinux 策略更改完成后,重新启动 MySQL 服务器:
service mysqld restart
卸载 LDAP 可插拔认证
卸载 LDAP 认证插件的方法取决于您如何安装它们:
-
如果您在服务器启动时使用
--plugin-load-add选项安装了插件,请在没有这些选项的情况下重新启动服务器。 -
如果您在运行时使用
INSTALL PLUGIN安装了插件,则它们将在服务器重新启动时保持安装状态。要卸载它们,请使用UNINSTALL PLUGIN:UNINSTALL PLUGIN authentication_ldap_simple; UNINSTALL PLUGIN authentication_ldap_sasl;
另外,从您的 my.cnf 文件中删除任何设置 LDAP 插件相关系统变量的启动选项。如果您使用 SET PERSIST 来持久化 LDAP 系统变量,请使用 RESET PERSIST 来删除这些设置。
LDAP 可插拔认证和 ldap.conf
对于使用 OpenLDAP 的安装,ldap.conf 文件为 LDAP 客户端提供全局默认值。可以在此文件中设置选项以影响 LDAP 客户端,包括 LDAP 认证插件。OpenLDAP 使用以下优先顺序的配置选项:
-
由 LDAP 客户端指定的配置。
-
在
ldap.conf文件中指定的配置。要禁用此文件的使用,请设置LDAPNOINIT环境变量。 -
OpenLDAP 库内置默认值。
如果库默认值或 ldap.conf 值不能产生适当的选项值,则 LDAP 认证插件可能能够设置相关变量以直接影响 LDAP 配置。例如,LDAP 插件可以覆盖 ldap.conf 中的参数,如:
-
TLS 配置:系统变量可用于启用 TLS 并控制 CA 配置,例如
authentication_ldap_simple_tls和authentication_ldap_simple_ca_path用于简单 LDAP 认证,以及authentication_ldap_sasl_tls和authentication_ldap_sasl_ca_path用于 SASL LDAP 认证。 -
LDAP 引荐。请参阅 LDAP 搜索引荐。
有关 ldap.conf 的更多信息,请参阅 ldap.conf(5) 手册页。
使用 LDAP 可插拔认证
本节描述了如何启用 MySQL 帐户使用 LDAP 可插拔认证连接到 MySQL 服务器。假设服务器正在运行,并启用了适当的服务器端插件,如安装 LDAP 可插拔认证中所述,并且客户端主机上有适当的客户端插件可用。
本节不描述 LDAP 配置或管理。假定您已熟悉这些主题。
两个服务器端 LDAP 插件分别与特定的客户端端插件配合使用:
-
服务器端
authentication_ldap_simple插件执行简单的 LDAP 身份验证。 对于使用此插件的帐户的连接,客户端程序使用客户端端mysql_clear_password插件,该插件将密码以明文形式发送到服务器。 不使用密码哈希或加密,因此建议在 MySQL 客户端和服务器之间建立安全连接,以防止密码泄露。 -
服务器端
authentication_ldap_sasl插件执行基于 SASL 的 LDAP 身份验证。 对于使用此插件的帐户的连接,客户端程序使用客户端端authentication_ldap_sasl_client插件。 客户端端和服务器端 SASL LDAP 插件使用 SASL 消息来在 LDAP 协议中安全传输凭据,以避免在 MySQL 客户端和服务器之间发送明文密码。
MySQL 用户 LDAP 身份验证的总体要求:
-
每个要进行身份验证的用户必须有一个 LDAP 目录条目。
-
必须有一个 MySQL 用户帐户,指定一个服务器端 LDAP 身份验证插件,并可选择命名相关的 LDAP 用户专有名称(DN)。 (要将 LDAP 用户 DN 与 MySQL 帐户关联,包括在创建帐户的
CREATE USER语句中包含一个BY子句。)如果帐户未命名任何 LDAP 字符串,则 LDAP 身份验证将使用客户端指定的用户名查找 LDAP 条目。 -
客户端程序使用适用于 MySQL 帐户使用的服务器端身份验证插件的连接方法进行连接。 对于 LDAP 身份验证,连接需要 MySQL 用户名和 LDAP 密码。 此外,对于使用服务器端
authentication_ldap_simple插件的帐户,使用--enable-cleartext-plugin选项调用客户端程序以启用客户端端mysql_clear_password插件。
此处的说明假定以下场景:
-
MySQL 用户
betsy和boris分别对betsy_ldap和boris_ldap的 LDAP 条目进行身份验证。(MySQL 和 LDAP 用户名不必不同。 在本讨论中使用不同名称有助于澄清操作上下文是 MySQL 还是 LDAP。) -
LDAP 条目使用
uid属性来指定用户名。 这可能会根据 LDAP 服务器而变化。 一些 LDAP 服务器使用cn属性而不是uid来表示用户名。 要更改属性,请适当修改authentication_ldap_simple_user_search_attr或authentication_ldap_sasl_user_search_attr系统变量。 -
这些 LDAP 条目可在 LDAP 服务器管理的目录中找到,以提供唯一标识每个用户的专有名称值:
uid=betsy_ldap,ou=People,dc=example,dc=com uid=boris_ldap,ou=People,dc=example,dc=com -
CREATE USER语句创建 MySQL 账户时,在BY子句中指定 LDAP 用户,以指示 MySQL 账户进行身份验证的 LDAP 条目。
使用 LDAP 认证设置帐户的说明取决于使用的服务器端 LDAP 插件。 以下各节描述了几种使用场景。
简单 LDAP 认证
要为简单 LDAP 认证配置 MySQL 账户,CREATE USER 语句指定 authentication_ldap_simple 插件,并可选择命名 LDAP 用户的区分名称(DN):
CREATE USER *user*
IDENTIFIED WITH authentication_ldap_simple
[BY '*LDAP user DN*'];
假设 MySQL 用户 betsy 在 LDAP 目录中有以下条目:
uid=betsy_ldap,ou=People,dc=example,dc=com
然后创建 betsy 的 MySQL 账户的语句如下:
CREATE USER 'betsy'@'localhost'
IDENTIFIED WITH authentication_ldap_simple
AS 'uid=betsy_ldap,ou=People,dc=example,dc=com';
在 BY 子句中指定的认证字符串不包括 LDAP 密码。 客户端用户必须在连接时提供密码。
客户端通过提供 MySQL 用户名和 LDAP 密码连接到 MySQL 服务器,并启用客户端端 mysql_clear_password 插件:
$> mysql --user=betsy --password --enable-cleartext-plugin
Enter password: *betsy_password* *(betsy_ldap LDAP password)*
注意
客户端端 mysql_clear_password 认证插件不会更改密码,因此客户端程序将其作为明文发送到 MySQL 服务器。 这使得密码可以原样传递到 LDAP 服务器。 在没有 SASL 的情况下使用服务器端 LDAP 库需要明文密码,但在某些配置中可能存在安全问题。 这些措施最小化了风险:
-
为了减少意外使用
mysql_clear_password插件的可能性,MySQL 客户端必须显式启用它(例如,使用--enable-cleartext-plugin选项)。 请参见 Section 8.4.1.4, “Client-Side Cleartext Pluggable Authentication”。 -
为了避免启用
mysql_clear_password插件时密码暴露,MySQL 客户端应该使用加密连接连接到 MySQL 服务器。 请参见 Section 8.3.1, “Configuring MySQL to Use Encrypted Connections”。
认证过程如下进行:
-
客户端插件将
betsy和betsy_password作为客户端用户名和 LDAP 密码发送到 MySQL 服务器。 -
连接尝试匹配
'betsy'@'localhost'账户。 服务器端 LDAP 插件发现该账户具有一个认证字符串'uid=betsy_ldap,ou=People,dc=example,dc=com'用于命名 LDAP 用户 DN。 该插件将此字符串和 LDAP 密码发送到 LDAP 服务器。 -
LDAP 服务器找到了
betsy_ldap的 LDAP 条目,并且密码匹配,因此 LDAP 认证成功。 -
LDAP 条目没有组属性,因此服务器端插件将客户端用户名(
betsy)作为经过身份验证的用户返回。这与客户端提供的相同用户名,因此不会发生代理,并且客户端会话使用'betsy'@'localhost'账户进行权限检查。
如果匹配的 LDAP 条目包含组属性,该属性值将成为经过身份验证的用户名,并且如果该值与betsy不同,则将发生代理。有关使用组属性的示例,请参阅具有代理功能的 LDAP 认证。
如果CREATE USER语句中没有包含BY子句来指定betsy_ldap LDAP 专有名称,认证尝试将使用客户端提供的用户名(在本例中为betsy)。在没有betsy的 LDAP 条目的情况下,认证将失败。
基于 SASL 的 LDAP 认证
要为 SASL LDAP 认证配置 MySQL 账户,CREATE USER 语句指定authentication_ldap_sasl插件,并可选择命名 LDAP 用户的专有名称(DN):
CREATE USER *user*
IDENTIFIED WITH authentication_ldap_sasl
[BY '*LDAP user DN*'];
假设 MySQL 用户boris在 LDAP 目录中有以下条目:
uid=boris_ldap,ou=People,dc=example,dc=com
然后创建boris的 MySQL 账户的语句如下:
CREATE USER 'boris'@'localhost'
IDENTIFIED WITH authentication_ldap_sasl
AS 'uid=boris_ldap,ou=People,dc=example,dc=com';
BY子句中指定的认证字符串不包括 LDAP 密码。这必须由客户端用户在连接时提供。
客户端通过提供 MySQL 用户名和 LDAP 密码连接到 MySQL 服务器:
$> mysql --user=boris --password
Enter password: *boris_password* *(boris_ldap LDAP password)*
对于服务器端的authentication_ldap_sasl插件,客户端使用客户端的authentication_ldap_sasl_client插件。如果客户端程序找不到客户端插件,请指定一个--plugin-dir选项,指定安装插件库文件的目录。
boris的认证过程与之前描述的betsy的简单 LDAP 认证类似,只是客户端和服务器端的 SASL LDAP 插件使用 SASL 消息来在 LDAP 协议中安全传输凭据,以避免在 MySQL 客户端和服务器之间发送明文密码。
具有代理功能的 LDAP 认证
LDAP 认证插件支持代理,使用户可以以一个用户连接到 MySQL 服务器,但假定另一个用户的权限。本节描述了基本的 LDAP 插件代理支持。LDAP 插件还支持指定组偏好和代理用户映射;请参阅 LDAP 认证组偏好和映射规范。
此处描述的代理实现基于使用 LDAP 组属性值将通过 LDAP 进行身份验证的连接 MySQL 用户映射到定义不同权限集的其他 MySQL 账户。用户不会直接通过定义权限的账户连接。相反,他们通过使用 LDAP 进行身份验证的默认代理账户连接,以便将所有外部登录映射到持有权限的代理 MySQL 账户。通过代理账户连接的任何用户都将映射到其中一个代理 MySQL 账户,其权限确定了允许外部用户执行的数据库操作。
此处的说明假定以下场景:
-
LDAP 条目使用
uid和cn属性分别指定用户名和组值。要使用不同的用户和组属性名称,请设置适当的插件特定系统变量:-
对于
authentication_ldap_simple插件:设置authentication_ldap_simple_user_search_attr和authentication_ldap_simple_group_search_attr。 -
对于
authentication_ldap_sasl插件:设置authentication_ldap_sasl_user_search_attr和authentication_ldap_sasl_group_search_attr。
-
-
这些 LDAP 条目可在由 LDAP 服务器管理的目录中找到,以提供唯一标识每个用户的可区分名称值:
uid=basha,ou=People,dc=example,dc=com,cn=accounting uid=basil,ou=People,dc=example,dc=com,cn=front_office在连接时,组属性值成为经过身份验证的用户名称,因此它们命名了
accounting和front_office代理账户。 -
示例假定使用 SASL LDAP 身份验证。对于简单 LDAP 身份验证,请进行适当调整。
创建默认的代理 MySQL 账户:
CREATE USER ''@'%'
IDENTIFIED WITH authentication_ldap_sasl;
代理账户定义中没有AS '*auth_string*'子句来命名 LDAP 用户 DN。因此:
-
当客户端连接时,客户端用户名将成为要搜索的 LDAP 用户名。
-
预期匹配的 LDAP 条目将包括命名定义客户端应具有的权限的代理 MySQL 账户的组属性。
注意
如果您的 MySQL 安装中存在匿名用户,则可能会与默认代理用户发生冲突。有关此问题的更多信息以及处理方法,请参阅默认代理用户和匿名用户冲突。
创建代理账户并授予每个账户应具有的权限:
CREATE USER 'accounting'@'localhost'
IDENTIFIED WITH mysql_no_login;
CREATE USER 'front_office'@'localhost'
IDENTIFIED WITH mysql_no_login;
GRANT ALL PRIVILEGES
ON accountingdb.*
TO 'accounting'@'localhost';
GRANT ALL PRIVILEGES
ON frontdb.*
TO 'front_office'@'localhost';
代理帐户使用mysql_no_login身份验证插件防止客户端直接使用帐户登录到 MySQL 服务器。相反,使用 LDAP 进行身份验证的用户应该使用默认的''@'%'代理帐户。(这假定安装了mysql_no_login插件。有关说明,请参见 Section 8.4.1.9, “No-Login Pluggable Authentication”。)有关保护代理帐户免受直接使用的替代方法,请参见 Preventing Direct Login to Proxied Accounts。
为每个代理帐户授予PROXY权限:
GRANT PROXY
ON 'accounting'@'localhost'
TO ''@'%';
GRANT PROXY
ON 'front_office'@'localhost'
TO ''@'%';
使用mysql命令行客户端连接到 MySQL 服务器作为basha。
$> mysql --user=basha --password
Enter password: *basha_password* *(basha LDAP password)*
认证过程如下:
-
服务器使用默认的
''@'%'代理帐户对客户端用户basha进行连接认证。 -
匹配的 LDAP 条目是:
uid=basha,ou=People,dc=example,dc=com,cn=accounting -
匹配的 LDAP 条目具有组属性
cn=accounting,因此accounting成为认证的代理用户。 -
认证用户与客户端用户名
basha不同,导致basha被视为accounting的代理,并且basha承担了代理accounting帐户的权限。以下查询返回如下输出:mysql> SELECT USER(), CURRENT_USER(), @@proxy_user; +-----------------+----------------------+--------------+ | USER() | CURRENT_USER() | @@proxy_user | +-----------------+----------------------+--------------+ | basha@localhost | accounting@localhost | ''@'%' | +-----------------+----------------------+--------------+
这表明basha使用授予代理accounting MySQL 帐户的权限,并且代理通过默认代理用户帐户进行。
现在改为连接为basil:
$> mysql --user=basil --password
Enter password: *basil_password* *(basil LDAP password)*
对于basil的身份验证过程与先前描述的basha类似:
-
服务器使用默认的
''@'%'代理帐户对客户端用户basil进行连接认证。 -
匹配的 LDAP 条目是:
uid=basil,ou=People,dc=example,dc=com,cn=front_office -
匹配的 LDAP 条目具有组属性
cn=front_office,因此front_office成为认证的代理用户。 -
认证用户与客户端用户名
basil不同,导致basil被视为front_office的代理,并且basil承担了代理front_office帐户的权限。以下查询返回如下输出:mysql> SELECT USER(), CURRENT_USER(), @@proxy_user; +-----------------+------------------------+--------------+ | USER() | CURRENT_USER() | @@proxy_user | +-----------------+------------------------+--------------+ | basil@localhost | front_office@localhost | ''@'%' | +-----------------+------------------------+--------------+
这表明basil使用授予代理front_office MySQL 帐户的权限,并且代理通过默认代理用户帐户进行。
LDAP 认证组首选项和映射规范
如 LDAP 代理认证中所述,基本的 LDAP 认证代理工作原理是插件使用 LDAP 服务器返回的第一个组名作为 MySQL 代理用户账户名。这种简单的功能不允许指定任何偏好,关于如果 LDAP 服务器返回多个组名该使用哪个,或者指定任何名称而不是组名作为代理用户名称。
截至 MySQL 8.0.14,对于使用 LDAP 认证的 MySQL 账户,认证字符串可以指定以下信息以实现更大的代理灵活性:
-
一组按照偏好顺序排列的组,使得插件使用列表中与 LDAP 服务器返回的组匹配的第一个组名。
-
从组名到代理用户名称的映射,使得匹配的组名可以提供指定的名称作为代理用户使用。这提供了一个替代方案,不使用组名作为代理用户。
考虑以下 MySQL 代理账户定义:
CREATE USER ''@'%'
IDENTIFIED WITH authentication_ldap_sasl
AS '+ou=People,dc=example,dc=com#grp1=usera,grp2,grp3=userc';
认证字符串有一个以+字符为前缀的用户 DN 后缀ou=People,dc=example,dc=com。因此,如 LDAP 认证用户 DN 后缀中所述,完整的用户 DN 是由指定的用户 DN 后缀加上客户端用户名作为uid属性构建而成。
认证字符串的剩余部分以#开头,表示组偏好和映射信息的开始。认证字符串的这部分按照grp1、grp2、grp3的顺序列出组名。LDAP 插件将该列表与 LDAP 服务器返回的组名集合进行比较,按照列表顺序查找与返回的名称匹配的组。插件使用第一个匹配项,如果没有匹配项,则认证失败。
假设 LDAP 服务器返回组grp3、grp2和grp7。LDAP 插件使用grp2,因为它是认证字符串中第一个匹配的组,即使它不是 LDAP 服务器返回的第一个组。如果 LDAP 服务器返回grp4、grp2和grp1,插件使用grp1,即使grp2也匹配。grp1的优先级高于grp2,因为它在认证字符串中较早列出。
假设插件找到组名匹配,它将从该组名映射到 MySQL 代理用户名称,如果有的话。对于示例代理账户,映射如下进行:
-
如果匹配的组名是
grp1或grp3,它们在认证字符串中与用户名称usera和userc相关联。插件使用相应的关联用户名称作为代理用户名称。 -
如果匹配的组名是
grp2,认证字符串中没有关联的用户名。插件使用grp2作为代理用户名称。
如果 LDAP 服务器以 DN 格式返回组,LDAP 插件会解析组 DN 以从中提取组名。
要指定 LDAP 组偏好和映射信息,应遵循以下原则:
-
用
#前缀字符开始认证字符串的组偏好和映射部分。 -
组偏好和映射规范是由逗号分隔的一个或多个项目的列表。每个项目的形式为
*group_name*=*user_name*或group_name。项目应按组名偏好顺序列出。对于插件从 LDAP 服务器返回的组名集合中选择的组名,两种语法在效果上有所不同:-
对于指定为
*group_name*=*user_name*(带有用户名)的项目,组名映射到用户名,该用户名用作 MySQL 代理用户名称。 -
对于指定为
group_name(没有用户名)的项目,组名用作 MySQL 代理用户名称。
-
-
要引用包含特殊字符(如空格)的组或用户名,用双引号 (
") 括起来。例如,如果一个项目的组名和用户名分别为my group name和my user name,则必须在组映射中使用引号:"my group name"="my user name"如果一个项目的组名和用户名分别为
my_group_name和my_user_name(不包含特殊字符),可以但不必使用引号。以下任何一种都是有效的:my_group_name=my_user_name my_group_name="my_user_name" "my_group_name"=my_user_name "my_group_name"="my_user_name" -
要转义字符,请在其前面加上反斜杠 (
\)。这对于包含文字双引号或反斜杠(否则不会被字面包含)特别有用。 -
用户 DN 不一定要出现在认证字符串中,但如果出现,必须在组偏好和映射部分之前。用户 DN 可以作为完整用户 DN 给出,也可以作为带有
+前缀字符的用户 DN 后缀给出。(参见 LDAP 认证用户 DN 后缀.)
LDAP 认证用户 DN 后缀
LDAP 认证插件允许提供用户 DN 信息的认证字符串以 + 前缀字符开头:
-
在没有
+字符的情况下,认证字符串值将按原样处理,不做修改。 -
如果认证字符串以
+开头,插件将从客户端发送的用户名和认证字符串中指定的 DN(去除+)构造完整的用户 DN 值。在构造的 DN 中,客户端用户名成为指定 LDAP 用户名的属性值。默认情况下为uid;要更改属性,请修改相应的系统变量(authentication_ldap_simple_user_search_attr或authentication_ldap_sasl_user_search_attr)。认证字符串存储在mysql.user系统表中,认证之前动态构造完整的用户 DN。
此帐户认证字符串不以+开头,因此被视为完整的用户 DN:
CREATE USER 'baldwin'
IDENTIFIED WITH authentication_ldap_simple
AS 'uid=admin,ou=People,dc=example,dc=com';
客户端使用帐户中指定的用户名(baldwin)连接。在这种情况下,该名称未被使用,因为认证字符串没有前缀,因此完全指定了用户 DN。
此帐户认证字符串以+开头,因此被视为用户 DN 的一部分:
CREATE USER 'accounting'
IDENTIFIED WITH authentication_ldap_simple
AS '+ou=People,dc=example,dc=com';
客户端使用帐户中指定的用户名(accounting)连接,该用户名与认证字符串一起用作构造用户 DN 的uid属性:uid=accounting,ou=People,dc=example,dc=com
前面示例中的帐户具有非空用户名,因此客户端始终使用帐户定义中指定的相同名称连接到 MySQL 服务器。如果帐户具有空用户名,例如使用代理进行 LDAP 认证中描述的默认匿名''@'%'代理帐户,客户端可能使用不同的用户名连接到 MySQL 服务器。但原则是相同的:如果认证字符串以+开头,插件将使用客户端发送的用户名和认证字符串一起构造用户 DN。
LDAP 认证方法
LDAP 认证插件使用可配置的认证方法。适当的系统变量和可用的方法选择是特定于插件的:
-
对于
authentication_ldap_simple插件:设置authentication_ldap_simple_auth_method_name系统变量以配置方法。允许的选择是SIMPLE和AD-FOREST。 -
对于
authentication_ldap_sasl插件:设置authentication_ldap_sasl_auth_method_name系统变量以配置方法。允许的选择是SCRAM-SHA-1、SCRAM-SHA-256和GSSAPI。(要确定主机系统上实际可用的 SASL LDAP 方法,请检查Authentication_ldap_sasl_supported_methods状态变量的值。)
有关每种允许方法的信息,请参阅系统变量描述。此外,根据方法的不同,可能需要额外的配置,如下面的部分所述。
GSSAPI/Kerberos 认证方法
通用安全服务应用程序接口(GSSAPI)是一个安全抽象接口。Kerberos 是可以通过该抽象接口使用的特定安全协议的一个实例。使用 GSSAPI,应用程序通过 Kerberos 进行身份验证以获取服务凭证,然后再使用这些凭证来实现对其他服务的安全访问。
其中一种服务是 LDAP,它被客户端和服务器端的 SASL LDAP 认证插件使用。当 authentication_ldap_sasl_auth_method_name 系统变量设置为 GSSAPI 时,这些插件使用 GSSAPI/Kerberos 认证方法。在这种情况下,插件通过 Kerberos 安全通信,而不直接使用 LDAP 消息。服务器端插件然后与 LDAP 服务器通信以解释 LDAP 认证消息并检索 LDAP 组。
GSSAPI/Kerberos 在 Linux 上作为 MySQL 服务器和客户端的 LDAP 认证方法得到支持。在 Linux 环境中,当应用程序通过默认启用 Kerberos 的 Microsoft Active Directory 访问 LDAP 时,这是非常有用的。
以下讨论提供了使用 GSSAPI 方法的配置要求信息。假定熟悉 Kerberos 概念和操作。以下列表简要定义了几个常见的 Kerberos 术语。您还可以在 RFC 4120 的术语表部分找到有用的信息。
-
主体:一个命名实体,比如用户或服务器。
-
KDC:密钥分发中心,包括 AS 和 TGS:
-
AS:认证服务器;提供获取额外票证所需的初始票证授予票证。
-
TGS:票证授予服务器;为拥有有效 TGT 的 Kerberos 客户端提供额外票证。
-
-
TGT:票据授予票据;提交给 TGS 以获取用于服务访问的服务票据。
使用 Kerberos 进行 LDAP 身份验证需要 KDC 服务器和 LDAP 服务器。可以通过不同方式满足此要求:
-
Active Directory 包括两个服务器,Active Directory LDAP 服务器默认启用 Kerberos 身份验证。
-
OpenLDAP 提供了一个 LDAP 服务器,但可能需要一个单独的 KDC 服务器,并需要额外的 Kerberos 设置。
客户端主机上也必须可用 Kerberos。客户端使用密码联系 AS 以获取 TGT。然后,客户端使用 TGT 从 TGS 获取其他服务的访问权限,例如 LDAP。
以下各节讨论了在 MySQL 中使用 GSSAPI/Kerberos 进行 SASL LDAP 身份验证的配置步骤:
-
验证 Kerberos 和 LDAP 的可用性
-
为 GSSAPI/Kerberos 配置服务器端 SASL LDAP 身份验证插件
-
创建一个使用 GSSAPI/Kerberos 进行 LDAP 身份验证的 MySQL 帐户
-
使用 MySQL 帐户连接到 MySQL 服务器
-
LDAP 身份验证的客户端配置参数
验证 Kerberos 和 LDAP 的可用性
以下示例显示如何在 Active Directory 中测试 Kerberos 的可用性。示例做出以下假设:
-
Active Directory 运行在名为
ldap_auth.example.com的主机上,IP 地址为198.51.100.10。 -
与 MySQL 相关的 Kerberos 身份验证和 LDAP 查找使用
MYSQL.LOCAL域。 -
名为
bredon@MYSQL.LOCAL的主体已在 KDC 中注册。(在后续讨论中,此主体名称还与使用 GSSAPI/Kerberos 对 MySQL 服务器进行身份验证的 MySQL 帐户相关联。)
在满足这些假设的情况下,按照以下步骤操作:
-
验证操作系统中 Kerberos 库是否已安装和配置正确。例如,要为 MySQL 身份验证期间使用
MYSQL.LOCAL域,/etc/krb5.confKerberos 配置文件应包含类似于以下内容:[realms] MYSQL.LOCAL = { kdc = ldap_auth.example.com admin_server = ldap_auth.example.com default_domain = MYSQL.LOCAL } -
您可能需要为服务器主机在
/etc/hosts中添加一个条目:198.51.100.10 ldap_auth ldap_auth.example.com -
检查 Kerberos 身份验证是否正常工作:
-
使用kinit进行 Kerberos 身份验证:
$> kinit bredon@MYSQL.LOCAL Password for bredon@MYSQL.LOCAL: *(enter password here)*该命令用于验证名为
bredon@MYSQL.LOCAL的 Kerberos 主体。当命令提示时,请输入主体的密码。KDC 返回一个 TGT,该 TGT 在客户端缓存中供其他支持 Kerberos 的应用程序使用。 -
使用klist检查 TGT 是否正确获取。输出应类似于以下内容:
$> klist Ticket cache: FILE:/tmp/krb5cc_244306 Default principal: bredon@MYSQL.LOCAL Valid starting Expires Service principal 03/23/2021 08:18:33 03/23/2021 18:18:33 krbtgt/MYSQL.LOCAL@MYSQL.LOCAL
-
-
使用此命令检查ldapsearch是否与 Kerberos TGT 一起工作,该命令在
MYSQL.LOCAL域中搜索用户:ldapsearch -h 198.51.100.10 -Y GSSAPI -b "dc=MYSQL,dc=LOCAL"
配置服务器端 SASL LDAP 认证插件以使用 GSSAPI/Kerberos
假设 LDAP 服务器可以通过上述方式访问 Kerberos,配置服务器端 SASL LDAP 认证插件以使用 GSSAPI/Kerberos 认证方法。(有关一般 LDAP 插件安装信息,请参阅安装 LDAP 可插入认证。)以下是服务器my.cnf文件可能包含的插件相关设���示例:
[mysqld]
plugin-load-add=authentication_ldap_sasl.so
authentication_ldap_sasl_auth_method_name="GSSAPI"
authentication_ldap_sasl_server_host=198.51.100.10
authentication_ldap_sasl_server_port=389
authentication_ldap_sasl_bind_root_dn="cn=admin,cn=users,dc=MYSQL,dc=LOCAL"
authentication_ldap_sasl_bind_root_pwd="*password*"
authentication_ldap_sasl_bind_base_dn="cn=users,dc=MYSQL,dc=LOCAL"
authentication_ldap_sasl_user_search_attr="sAMAccountName"
这些选项文件设置配置了 SASL LDAP 插件如下:
-
--plugin-load-add选项加载插件(根据需要调整.so后缀以适应您的平台)。如果之前使用INSTALL PLUGIN语句加载了插件,则此选项是不必要的。 -
authentication_ldap_sasl_auth_method_name必须设置为GSSAPI以使用 GSSAPI/Kerberos 作为 SASL LDAP 认证方法。 -
authentication_ldap_sasl_server_host和authentication_ldap_sasl_server_port指示用于身份验证的 Active Directory 服务器主机的 IP 地址和端口号。 -
authentication_ldap_sasl_bind_root_dn和authentication_ldap_sasl_bind_root_pwd配置了用于组搜索功能的根 DN 和密码。此功能是必需的,但用户可能没有搜索权限。在这种情况下,有必要提供根 DN 信息:-
在 DN 选项值中,
admin应该是具有执行用户搜索权限的管理 LDAP 帐户的名称。 -
在密码选项值中,*
password*应该是admin帐户的密码。
-
-
authentication_ldap_sasl_bind_base_dn指示用户 DN 基本路径,以便搜索在MYSQL.LOCAL域中的用户。 -
authentication_ldap_sasl_user_search_attr指定了一个标准的 Active Directory 搜索属性,sAMAccountName。此属性用于搜索以匹配登录名;属性值与用户 DN 值不同。
创建一个使用 GSSAPI/Kerberos 进行 LDAP 认证的 MySQL 账户
使用 GSSAPI/Kerberos 方法的 SASL LDAP 认证插件进行 MySQL 认证是基于一个作为 Kerberos 主体的用户。以下讨论使用一个名为 bredon@MYSQL.LOCAL 的主体作为此用户,必须在多个地方注册:
-
Kerberos 管理员应该将用户名称注册为 Kerberos 主体。此名称应包括域名。客户端使用主体名称和密码进行 Kerberos 认证并获取 TGT。
-
LDAP 管理员应在 LDAP 条目中注册用户名称。例如:
uid=bredon,dc=MYSQL,dc=LOCAL注意
在 Active Directory(默认使用 Kerberos 作为认证方法),创建用户会同时创建 Kerberos 主体和 LDAP 条目。
-
MySQL DBA 应创建一个账户,其用户名称为 Kerberos 主体名称,并使用 SASL LDAP 插件进行认证。
假设适当的服务管理员已经注册了 Kerberos 主体和 LDAP 条目,并且,如前面在 Installing LDAP Pluggable Authentication 和 Configure the Server-Side SASL LDAP Authentication Plugin for GSSAPI/Kerberos 中描述的那样,MySQL 服务器已经以适当的配置设置启动了服务器端 SASL LDAP 插件。然后 MySQL DBA 创建一个对应于 Kerberos 主体名称的 MySQL 账户,包括域名。
注意
SASL LDAP 插件对于 Kerberos 认证使用一个固定的用户 DN,并忽略从 MySQL 配置的任何用户 DN。这有一定的影响:
-
对于使用 GSSAPI/Kerberos 认证的任何 MySQL 账户,在
CREATE USER或ALTER USER语句中的认证字符串不应包含用户 DN,因为它没有任何效果。 -
因为认证字符串不包含用户 DN,所以应包含组映射信息,以使用户能够作为映射到所需代理用户的代理用户进行处理。有关使用 LDAP 认证插件进行代理的信息,请参阅 LDAP Authentication with Proxying。
以下语句创建一个名为bredon@MYSQL.LOCAL的代理用户,该用户假定了被代理用户proxied_krb_usr的权限。其他应具有相同权限的 GSSAPI/Kerberos 用户可以类似地为同一被代理用户创建代理用户。
-- create proxy account
CREATE USER 'bredon@MYSQL.LOCAL'
IDENTIFIED WITH authentication_ldap_sasl
BY '#krb_grp=proxied_krb_user';
-- create proxied account and grant its privileges;
-- use mysql_no_login plugin to prevent direct login
CREATE USER 'proxied_krb_user'
IDENTIFIED WITH mysql_no_login;
GRANT ALL
ON krb_user_db.*
TO 'proxied_krb_user';
-- grant to proxy account the
-- PROXY privilege for proxied account
GRANT PROXY
ON 'proxied_krb_user'
TO 'bredon@MYSQL.LOCAL';
仔细观察第一个CREATE USER语句和GRANT PROXY语句中代理账户名称的引用:
-
对于大多数 MySQL 账户,用户和主机是账户名称的独立部分,因此分别引用为
'*user_name*'@'*host_name*'。 -
对于 LDAP Kerberos 认证,账户名称的用户部分包括主体域,因此
'bredon@MYSQL.LOCAL'被引用为单个值。因为没有给出主机部分,所以完整的 MySQL 账户名称使用默认的'%'作为主机部分:'bredon@MYSQL.LOCAL'@'%'
注意
当创建一个使用 GSSAPI/Kerberos 认证方法的authentication_ldap_sasl SASL LDAP 认证插件进行身份验证的账户时,CREATE USER语句将领域作为用户名的一部分。这与使用authentication_kerberos Kerberos 插件创建账户不同。对于这样的账户,CREATE USER语句不包括领域作为用户名的一部分。而是在BY子句中指定领域作为认证字符串。请参阅创建使用 Kerberos 认证的 MySQL 账户。
被代理账户使用mysql_no_login认证插件防止客户端直接使用该账户登录到 MySQL 服务器。相反,预期使用 LDAP 进行身份验证的用户使用bredon@MYSQL.LOCAL代理账户。(这假设已安装mysql_no_login插件。有关说明,请参见第 8.4.1.9 节,“无登录可插入认证”。)有关保护被代理账户免受直接使用的替代方法,请参见防止直接登录到被代理账户。
使用 MySQL 账户连接到 MySQL 服务器
设置使用 GSSAPI/Kerberos 进行身份验证的 MySQL 账户后,客户端可以使用它连接到 MySQL 服务器。Kerberos 认证可以在 MySQL 客户端程序调用之前或同时进行:
-
在调用 MySQL 客户端程序之前,客户端用户可以独立于 MySQL 从 KDC 获取 TGT。例如,客户端用户可以使用kinit通过提供 Kerberos 主体名称和主体密码来对 Kerberos 进行身份验证:
$> kinit bredon@MYSQL.LOCAL Password for bredon@MYSQL.LOCAL: *(enter password here)*结果的 TGT 被缓存并可供其他了解 Kerberos 的应用程序使用,例如使用客户端端 SASL LDAP 认证插件的程序。在这种情况下,MySQL 客户端程序使用 TGT 对 MySQL 服务器进行认证,因此调用客户端时不需要指定用户名或密码:
mysql --default-auth=authentication_ldap_sasl_client正如刚才所描述的,当 TGT 被缓存时,在客户端命令中不需要用户名称和密码选项。如果命令中仍然包含它们,则处理如下:
-
如果命令包含用户名,如果该名称与 TGT 中的主体名称不匹配,则认证失败。
-
如果命令包含密码,客户端插件会忽略它。因为认证是基于 TGT 的,即使用户提供的密码不正确,也可以成功。因此,如果找到有效的 TGT 导致密码被忽略,插件会产生警告。
-
-
如果 Kerberos 缓存中不包含 TGT,则客户端端 SASL LDAP 认证插件本身可以从 KDC 获取 TGT。使用与 MySQL 账户关联的 Kerberos 主体的名称和密码选项调用客户端(在提示时输入主体密码):
mysql --default-auth=authentication_ldap_sasl_client --user=bredon@MYSQL.LOCAL --password -
如果 Kerberos 缓存中不包含 TGT,并且客户端命令未指定主体名称作为用户名,则认证失败。
如果您不确定是否存在 TGT,可以使用 klist 进行检查。
认证过程如下:
-
客户端使用 TGT 使用 Kerberos 进行认证。
-
服务器找到主体的 LDAP 条目并用它来认证连接到
bredon@MYSQL.LOCALMySQL 代理账户。 -
代理账户认证字符串中的组映射信息(
'#krb_grp=proxied_krb_user')表示认证的被代理用户应该是proxied_krb_user。 -
bredon@MYSQL.LOCAL被视为proxied_krb_user的代理,并且以下查询返回如下输出:mysql> SELECT USER(), CURRENT_USER(), @@proxy_user; +------------------------------+--------------------+--------------------------+ | USER() | CURRENT_USER() | @@proxy_user | +------------------------------+--------------------+--------------------------+ | bredon@MYSQL.LOCAL@localhost | proxied_krb_user@% | 'bredon@MYSQL.LOCAL'@'%' | +------------------------------+--------------------+--------------------------+USER()值表示用于客户端命令的用户名(bredon@MYSQL.LOCAL)和客户端连接的主机(localhost)。CURRENT_USER()值是被代理用户账户的全名,由proxied_krb_user用户部分和%主机部分组成。@@proxy_user值表示用于连接到 MySQL 服务器的账户的全名,由bredon@MYSQL.LOCAL用户部分和%主机部分组成。这表明代理是通过
bredon@MYSQL.LOCAL代理用户账户进行的,并且bredon@MYSQL.LOCAL承担了授予proxied_krb_user被代理用户账户的权限。
一旦获得 TGT,客户端会将其缓存在本地,并且在不再需要重新输入密码的情况下可以一直使用直到过期。无论如何获取 TGT,客户端插件都会使用它来获取服务票据并与服务器端插件通信。
注意
当客户端身份验证插件本身获取 TGT 时,客户端用户可能不希望 TGT 被重复使用。如 LDAP 身份验证的客户端配置参数所述,本地的/etc/krb5.conf文件可用于使客户端插件在完成后销毁 TGT。
服务器端插件无法访问 TGT 本身或用于获取 TGT 的 Kerberos 密码。
LDAP 身份验证插件无法控制缓存机制(存储在本地文件中、内存中等),但 Kerberos 实用程序如kswitch可能可用于此目的。
LDAP 身份验证的客户端配置参数
authentication_ldap_sasl_client客户端端 SASL LDAP 插件会读取本地的/etc/krb5.conf文件。如果该文件丢失或无法访问,将会出现错误。假设该文件可访问,它可以包含一个可选的[appdefaults]部分,提供插件使用的信息。将信息放在部分的mysql部分内。例如:
[appdefaults]
mysql = {
ldap_server_host = "ldap_host.example.com"
ldap_destroy_tgt = true
}
客户端插件在mysql部分识别这些参数:
-
ldap_server_host值指定 LDAP 服务器主机,当该主机与[realms]部分指定的 KDC 服务器主机不同时,这可能很有用。默认情况下,插件使用 KDC 服务器主机作为 LDAP 服务器主机。 -
ldap_destroy_tgt值指示客户端插件在获取和使用 TGT 后是否销毁 TGT。默认情况下,ldap_destroy_tgt为false,但可以设置为true以避免 TGT 重复使用。(此设置仅适用于由客户端插件创建的 TGT,不适用于由 MySQL 的其他插件或外部创建的 TGT。)
LDAP 搜索引荐
LDAP 服务器可以配置为将 LDAP 搜索委派给另一个 LDAP 服务器,这种功能称为 LDAP 引荐。假设服务器a.example.com拥有一个"dc=example,dc=com"根 DN,并希望将搜索委派给另一个服务器b.example.com。为了启用这个功能,a.example.com将被配置为具有以下属性的命名引荐对象:
dn: dc=subtree,dc=example,dc=com
objectClass: referral
objectClass: extensibleObject
dc: subtree
ref: ldap://b.example.com/dc=subtree,dc=example,dc=com
启用 LDAP 引荐的一个问题是,当搜索基本 DN 为根 DN 且未设置引荐对象时,搜索可能会因 LDAP 操作错误而失败。即使在ldap.conf配置文件中全局设置了 LDAP 引荐,MySQL DBA 可能希望避免 LDAP 认证插件出现此类引荐错误。要根据插件特定的基础配置 LDAP 服务器在与每个插件通信时是否应使用 LDAP 引荐,需设置authentication_ldap_simple_referral和authentication_ldap_sasl_referral系统变量。将任一变量设置为ON或OFF会导致相应的 LDAP 认证插件告知 LDAP 服务器在 MySQL 认证期间是否使用引荐。每个变量具有插件特定的效果,不会影响与 LDAP 服务器通信的其他应用程序。这两个变量默认为OFF。
原文:
dev.mysql.com/doc/refman/8.0/en/kerberos-pluggable-authentication.html
8.4.1.8 Kerberos 可插拔认证
注意
Kerberos 可插拔认证是 MySQL 企业版中包含的扩展,这是一个商业产品。要了解更多关于商业产品的信息,请参见www.mysql.com/products/。
MySQL 企业版支持一种认证方法,允许用户使用 Kerberos 对 MySQL 服务器进行身份验证,前提是有适当的 Kerberos 票证可用或可以获取。
该认证方法适用于 MySQL 8.0.26 及更高版本,在 Linux 上的 MySQL 服务器和客户端。在 Linux 环境中,应用程序可以访问默认启用 Kerberos 的 Microsoft Active Directory 时,这是非常有用的。从 MySQL 8.0.27 开始(MIT Kerberos 的 MySQL 8.0.32),客户端端插件也在 Windows 上受支持。服务器端插件仍然只在 Linux 上受支持。
Kerberos 可插拔认证提供了以下功能:
-
外部认证:Kerberos 认证使 MySQL 服务器能够接受来自 MySQL 授权表之外定义的用户的连接,这些用户已经获得了适当的 Kerberos 票证。
-
安全性:Kerberos 使用票证与对称密钥加密结合,实现了在网络上传输密码的身份验证。Kerberos 认证支持无用户和无密码的场景。
以下表显示了插件和库文件名称。文件名后缀可能在您的系统上有所不同。该文件必须位于由plugin_dir系统变量命名的目录中。有关安装信息,请参见安装 Kerberos 可插拔认证。
表 8.24 Kerberos 认证的插件和库名称
| 插件或文件 | 插件或文件名 |
|---|---|
| 服务器端插件 | authentication_kerberos |
| 客户端插件 | authentication_kerberos_client |
| 库文件 | authentication_kerberos.so,authentication_kerberos_client.so |
服务器端 Kerberos 认证插件仅包含在 MySQL 企业版中。它不包含在 MySQL 社区发行版中。客户端插件包含在所有发行版中,包括社区发行版。这使得来自任何发行版的客户端都可以连接到加载了服务器端插件的服务器。
以下各节提供了特定于 Kerberos 可插拔认证的安装和使用信息:
-
Kerberos 可插拔认证的先决条件
-
MySQL 用户的 Kerberos 认证工作原理
-
安装 Kerberos 可插拔认证
-
使用 Kerberos 可插拔认证
-
Kerberos 认证调试
有关 MySQL 中可插拔认证的一般信息,请参阅 第 8.2.17 节,“可插拔认证”。
Kerberos 可插拔认证的先决条件
要在 MySQL 中使用可插拔的 Kerberos 认证,必须满足以下先决条件:
-
必须提供一个 Kerberos 服务,以便 Kerberos 认证插件进行通信。
-
MySQL 要对其进行认证的每个 Kerberos 用户(主体)必须存在于 KDC 服务器管理的数据库中。
-
在使用服务器端或客户端 Kerberos 认证插件的系统上必须提供 Kerberos 客户端库。此外,GSSAPI 用作访问 Kerberos 认证的接口,因此必须提供 GSSAPI 库。
MySQL 用户的 Kerberos 认证工作原理
本节概述了 MySQL 和 Kerberos 如何共同工作以对 MySQL 用户进行认证。有关如何设置 MySQL 帐户以使用 Kerberos 认证插件的示例,请参阅 使用 Kerberos 可插拔认证。
假定读者熟悉 Kerberos 的概念和操作。以下列表简要定义了几个常见的 Kerberos 术语。您还可以在 RFC 4120 的术语表部分找到有用的信息。
-
主体:命名实体,如用户或服务器。在本讨论中,某些与主体相关的术语经常出现:
-
SPN:服务主体名称;代表服务的主体名称。
-
UPN:用户主体名称;代表用户的主体名称。
-
-
KDC:密钥分发中心,包括 AS 和 TGS:
-
AS:认证服务器;提供获取额外票证所需的初始票证授予票证。
-
TGS:票据授予服务器;为拥有有效 TGT 的 Kerberos 客户端提供额外的票据。
-
-
TGT:票据授予票据;提交给 TGS 以获取用于服务访问的服务票据。
-
ST:服务票据;提供对 MySQL 服务器等服务的访问。
使用 Kerberos 进行身份验证需要一个 KDC 服务器,例如,由 Microsoft Active Directory 提供。
MySQL 中的 Kerberos 认证使用通用安全服务应用程序接口(GSSAPI),这是一个安全抽象接口。Kerberos 是可以通过该抽象接口使用的特定安全协议的一个实例。使用 GSSAPI,应用程序进行身份验证以获取服务凭据,然后依次使用这些凭据来启用对其他服务的安全访问。
在 Windows 上,authentication_kerberos_client 认证插件支持两种模式,客户端用户可以在运行时设置或在选项文件中指定:
-
SSPI模式:安全支持提供程序接口(SSPI)实现了 GSSAPI(参见 SSPI 模式下的 Windows 客户端命令)。SSPI 在传输层面与 GSSAPI 兼容,但仅支持 Windows 单点登录场景,并且专门指代已登录用户。SSPI 是大多数 Windows 客户端的默认模式。 -
GSSAPI模式:在 Windows 上通过 MIT Kerberos 库支持 GSSAPI(参见 GSSAPI 模式下的 Windows 客户端命令)。
使用 Kerberos 认证插件,应用程序和 MySQL 服务器能够使用 Kerberos 认证协议相互认证用户和 MySQL 服务。这样,用户和服务器都能够验证彼此的身份。不会通过网络发送密码,并且 Kerberos 协议消息受到窃听和重放攻击的保护。
MySQL 中的 Kerberos 认证遵循这些步骤,其中服务器端和客户端部分分别使用 authentication_kerberos 和 authentication_kerberos_client 认证插件执行:
-
MySQL 服务器向客户端应用程序发送其服务主体名称。此 SPN 必须在 Kerberos 系统中注册,并且在服务器端使用
authentication_kerberos_service_principal系统变量进行配置。 -
使用 GSSAPI,客户端应用程序创建一个 Kerberos 客户端端身份验证会话,并与 Kerberos KDC 交换 Kerberos 消息:
-
客户端从认证服务器获取票据授予票据。
-
使用 TGT,客户端从票据授予服务获取 MySQL 的服务票据。
如果 TGT、ST 或两者都已在本地缓存,则可以跳过或部分跳过此步骤。客户端可以选择使用客户端 keytab 文件来获取 TGT 和 ST,而无需提供密码。
-
-
使用 GSSAPI,客户端应用程序向 MySQL 服务器呈现 MySQL ST。
-
使用 GSSAPI,MySQL 服务器创建一个 Kerberos 服务器端认证会话。服务器验证用户身份和用户请求的有效性。它使用其服务 keytab 文件中配置的服务密钥验证 ST,以确定身份验证成功或失败,并将身份验证结果返回给客户端。
应用程序可以使用提供的用户名和密码进行身份验证,也可以使用本地缓存的 TGT 或 ST(例如,使用 kinit 或类似方法创建)。因此,此设计涵盖了各种用例,从完全无用户和无密码连接,其中 Kerberos 服务票据是从本地存储的 Kerberos 缓存获取的,到提供并使用用户名和密码以获取有效的 Kerberos 服务票据从 KDC 发送到 MySQL 服务器的连接。
如前述描述所示,MySQL 的 Kerberos 认证使用两种类型的 keytab 文件:
-
在客户端主机上,可以使用客户端 keytab 文件来获取 TGT 和 ST,而无需提供密码。请参阅 Client Configuration Parameters for Kerberos Authentication。
-
在 MySQL 服务器主机上,使用服务器端服务 keytab 文件来验证 MySQL 服务器从客户端接收的服务票据。 keytab 文件名是使用
authentication_kerberos_service_key_tab系统变量配置的。
有关 keytab 文件的信息,请参阅 web.mit.edu/kerberos/krb5-latest/doc/basic/keytab_def.html。
安装 Kerberos 可插拔认证
本节描述了如何安装服务器端 Kerberos 认证插件。有关安装插件的一般信息,请参阅 Section 7.6.1, “Installing and Uninstalling Plugins”。
注意
服务器端插件仅在 Linux 系统上受支持。在 Windows 系统上,仅支持客户端端插件(截至 MySQL 8.0.27),可以在 Windows 系统上用于连接使用 Kerberos 认证的 Linux 服务器。
要使服务器可用,插件库文件必须位于 MySQL 插件目录中(由plugin_dir系统变量命名的目录)。必要时,通过设置plugin_dir的值来配置插件目录位置以在服务器启动时生效。
服务器端插件库文件基本名称为authentication_kerberos。Unix 和类 Unix 系统的文件名后缀为.so。
要在服务器启动时加载插件,请使用--plugin-load-add选项命名包含插件的库文件。使用此插件加载方法,每次服务器启动时都必须提供该选项。还要为您希望配置的任何插件提供的系统变量指定值。插件公开这些系统变量,使其操作可以配置:
-
authentication_kerberos_service_principal: MySQL 服务主体名称(SPN)。此名称将发送给尝试使用 Kerberos 进行身份验证的客户端。SPN 必须存在于 KDC 服务器管理的数据库中。默认值为mysql/*host_name*@*realm_name*。 -
authentication_kerberos_service_key_tab: 用于验证从客户端接收到的票证的 keytab 文件。此文件必须存在并包含 SPN 的有效密钥,否则客户端的身份验证将失败。默认值为数据目录中的mysql.keytab。
有关所有 Kerberos 身份验证系统变量的详细信息,请参见 Section 8.4.1.13, “Pluggable Authentication System Variables”。
要加载插件并配置它,请在您的my.cnf文件中放入类似以下行的内容,使用适合您安装的系统变量的值:
[mysqld]
plugin-load-add=authentication_kerberos.so
authentication_kerberos_service_principal=mysql/krbauth.example.com@MYSQL.LOCAL
authentication_kerberos_service_key_tab=/var/mysql/data/mysql.keytab
修改my.cnf后,重新启动服务器以使新设置生效。
或者,要在运行时加载插件,请使用以下语句:
INSTALL PLUGIN authentication_kerberos
SONAME 'authentication_kerberos.so';
INSTALL PLUGIN立即加载插件,并在mysql.plugins系统表中注册它,以使服务器在每次后续正常启动时加载它,而无需--plugin-load-add。
当您在运行时安装插件而没有在my.cnf文件中配置其系统变量时,系统变量 authentication_kerberos_service_key_tab 将设置为数据目录中的默认值mysql.keytab。此系统变量的值不能在运行时更改,因此如果需要指定不同的文件,您需要将设置添加到您的my.cnf文件,然后重新启动 MySQL 服务器。例如:
[mysqld]
authentication_kerberos_service_key_tab=/var/mysql/data/mysql.keytab
如果 keytab 文件不在正确的位置或不包含有效的 SPN 密钥,则 MySQL 服务器不会验证此问题,但客户端会返回身份验证错误,直到您解决问题。
authentication_kerberos_service_principal 系统变量可以在运行时使用 SET PERSIST 语句设置和持久化,而无需重新启动服务器:
SET PERSIST authentication_kerberos_service_principal='mysql/krbauth.example.com@MYSQL.LOCAL';
SET PERSIST 为运行中的 MySQL 实例设置一个值。它还保存该值,导致其在后续服务器重启时保留。要更改运行中的 MySQL 实例的值,而不使其在后续重启中保留,使用GLOBAL关键字而不是PERSIST。参见 Section 15.7.6.1, “变量赋值的 SET 语法”。
要验证插件安装,请检查信息模式 PLUGINS 表或使用 SHOW PLUGINS 语句(参见 Section 7.6.2, “获取服务器插件信息”)。例如:
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
FROM INFORMATION_SCHEMA.PLUGINS
WHERE PLUGIN_NAME = 'authentication_kerberos';
+-------------------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+-------------------------+---------------+
| authentication_kerberos | ACTIVE |
+-------------------------+---------------+
如果插件初始化失败,请检查服务器错误日志以获取诊断信息。
要将 MySQL 帐户与 Kerberos 插件关联,请参见 使用 Kerberos 可插拔认证。
使用 Kerberos 可插拔认证
本节描述了如何启用 MySQL 帐户使用 Kerberos 可插拔认证连接到 MySQL 服务器。假定服务器正在运行并启用了服务器端插件,如 安装 Kerberos 可插拔认证 中所述,并且客户端主机上可用客户端插件。
-
验证 Kerberos 可用性
-
创建一个使用 Kerberos 身份验证的 MySQL 帐户
-
使用 MySQL 帐户连接到 MySQL 服务器
-
Kerberos 身份验证的客户端配置参数
验证 Kerberos 的可用性
以下示例显示如何测试 Active Directory 中 Kerberos 的可用性。该示例做出以下假设:
-
Active Directory 正在名为
krbauth.example.com的主机上运行,IP 地址为198.51.100.11。 -
与 MySQL 相关的 Kerberos 身份验证使用
MYSQL.LOCAL域,并且还使用MYSQL.LOCAL作为领域名称。 -
名为
karl@MYSQL.LOCAL的主体已在 KDC 中注册。(在后续讨论中,此主体名称与使用 Kerberos 身份验证连接到 MySQL 服务器的 MySQL 帐户相关联。)
在满足这些假设的情况下,按照以下步骤进行:
-
验证操作系统中是否正确安装和配置了 Kerberos 库。例如,要在 MySQL 身份验证期间使用
MYSQL.LOCAL域和领域,/etc/krb5.confKerberos 配置文件应包含类似于以下内容:[realms] MYSQL.LOCAL = { kdc = krbauth.example.com admin_server = krbauth.example.com default_domain = MYSQL.LOCAL } -
您可能需要为服务器主机在
/etc/hosts中添加一个条目:198.51.100.11 krbauth krbauth.example.com -
检查 Kerberos 身份验证是否正常工作:
-
使用kinit进行 Kerberos 身份验证:
$> kinit karl@MYSQL.LOCAL Password for karl@MYSQL.LOCAL: *(enter password here)*该命令对名为
karl@MYSQL.LOCAL的 Kerberos 主体进行身份验证。当命令提示时输入主体密码。KDC 返回一个 TGT,该 TGT 在客户端缓存以供其他了解 Kerberos 的应用程序使用。 -
使用klist检查 TGT 是否正确获取。输出应类似于以下内容:
$> klist Ticket cache: FILE:/tmp/krb5cc_244306 Default principal: karl@MYSQL.LOCAL Valid starting Expires Service principal 03/23/2021 08:18:33 03/23/2021 18:18:33 krbtgt/MYSQL.LOCAL@MYSQL.LOCAL
-
创建一个使用 Kerberos 身份验证的 MySQL 帐户
使用authentication_kerberos身份验证插件进行 MySQL 身份验证基于 Kerberos 用户主体名称(UPN)。这里的说明假设一个名为karl的 MySQL 用户使用 Kerberos 进行 MySQL 身份验证,Kerberos 领域命名为MYSQL.LOCAL,用户主体名称为karl@MYSQL.LOCAL。这个 UPN 必须在几个地方注册:
-
Kerberos 管理员应将用户名称注册为 Kerberos 主体。此名称包括领域名称。客户端使用主体名称和密码进行 Kerberos 身份验证,并获取票据授予票据(TGT)。
-
MySQL DBA 应创建一个与 Kerberos 主体名称对应并使用 Kerberos 插件进行身份验证的帐户。
假设适当的服务管理员已注册了 Kerberos 用户主体名称,并且如前所述在安装 Kerberos 可插拔认证中,MySQL 服务器已使用适当的配置设置启动了服务器端 Kerberos 插件。要创建与 Kerberos UPN *user*@*realm_name*对应的 MySQL 帐户,MySQL DBA 使用类似于以下语句:
CREATE USER *user*
IDENTIFIED WITH authentication_kerberos
BY '*realm_name*';
由*user指定的帐户可以包含或省略主机名部分。如果省略主机名,则通常默认为%。realm_name*存储为mysql.user系统表中帐户的authentication_string值。
要创建与 UPN karl@MYSQL.LOCAL对应的 MySQL 帐户,请使用此语句:
CREATE USER 'karl'
IDENTIFIED WITH authentication_kerberos
BY 'MYSQL.LOCAL';
如果 MySQL 必须为此帐户构造 UPN,例如获取或验证票证(TGT 或 ST),则通过组合帐户名(忽略任何主机名部分)和领域名来执行此操作。例如,从前述CREATE USER语句中得到的完整帐户名为'karl'@'%'。MySQL 从用户名部分karl(忽略主机名部分)和领域名MYSQL.LOCAL构造 UPN,以生成karl@MYSQL.LOCAL。
注意
请注意,当创建使用authentication_kerberos进行身份验证的帐户时,CREATE USER语句不包括 UPN 领域作为用户名的一部分。而是在BY子句中指定领域(在本例中为MYSQL.LOCAL)作为认证字符串。这与使用 GSSAPI/Kerberos 认证方法的authentication_ldap_sasl SASL LDAP 认证插件创建帐户不同。对于这样的帐户,CREATE USER语句包括 UPN 领域作为用户名的一部分。请参阅创建使用 GSSAPI/Kerberos 进行 LDAP 认证的 MySQL 帐户。
设置好帐户后,客户端可以使用它连接到 MySQL 服务器。该过程取决于客户端主机是运行 Linux 还是 Windows,如下面的讨论所示。
使用authentication_kerberos受到限制,即不支持具有相同用户部分但不同领域部分的 UPN。例如,您不能创建对应于以下这两个 UPN 的 MySQL 帐户:
kate@MYSQL.LOCAL
kate@EXAMPLE.COM
两个 UPN 都具有kate的用户部分,但领域部分不同(MYSQL.LOCAL与EXAMPLE.COM)。这是不允许的。
使用 MySQL 帐户连接到 MySQL 服务器
设置了使用 Kerberos 进行身份验证的 MySQL 帐户后,客户端可以按以下方式连接到 MySQL 服务器:
-
使用用户主体名称(UPN)和其密码对 Kerberos 进行身份验证,以获取票据授予票据(TGT)。
-
使用 TGT 获取 MySQL 的服务票据(ST)。
-
通过呈现 MySQL ST 向 MySQL 服务器进行身份验证。
第一步(向 Kerberos 进行身份验证)可以通过各种方式执行:
-
在连接到 MySQL 之前:
-
在 Linux 或在
GSSAPI模式下的 Windows 上,调用kinit以获取 TGT 并将其保存在 Kerberos 凭据缓存中。 -
在
SSPI模式下的 Windows 中,认证可能已在登录时完成,这会将登录用户的 TGT 保存在 Windows 内存缓存中。kinit不会被使用,也没有 Kerberos 缓存。
-
-
连接到 MySQL 时,客户端程序本身可以获取 TGT,如果它可以确定所需的 Kerberos UPN 和密码:
-
信息可以来自诸如命令选项或操作系统之类的来源。
-
在 Linux 上,客户端还可以使用 keytab 文件或
/etc/krb5.conf配置文件。在GSSAPI模式下的 Windows 客户端使用配置文件。在SSPI模式下��Windows 客户端两者都不使用。
-
连接到 MySQL 服务器的客户端命令的详细信息因 Linux 和 Windows 而异,因此每个主机类型都会单独讨论,但这些命令属性适用于所有主机类型:
-
每个显示的命令都包括以下选项,但在某些情况下可以省略每个选项:
-
--default-auth选项指定客户端端身份验证插件的名称(authentication_kerberos_client)。当指定--user选项时,可以省略此选项,因为在这种情况下,MySQL 可以从 MySQL 服务器发送的用户帐户信息中确定插件。 -
--plugin-dir选项指示客户端程序authentication_kerberos_client插件的位置。如果插件安装在默认(编译内)位置,则可以省略此选项。
-
-
命令还应包括任何其他选项,如
--host或--port,以指定连接到哪个 MySQL 服务器。 -
每个命令都要单独输入一行。如果命令包括
--password选项以获取密码,请在提示时输入与 MySQL 用户关联的 Kerberos UPN 的密码。
Linux 客户端连接命令
在 Linux 上,连接到 MySQL 服务器的适当客户端命令因命令是使用来自 Kerberos 缓存的 TGT 进行身份验证,还是基于 MySQL 用户名和 UPN 密码的命令选项而异:
-
在调用 MySQL 客户端程序之前,客户端用户可以独立于 MySQL 从 KDC 获取 TGT。例如,客户端用户可以使用kinit通过提供 Kerberos 用户主体名称和主体密码来对 Kerberos 进行身份验证:
$> kinit karl@MYSQL.LOCAL Password for karl@MYSQL.LOCAL: *(enter password here)*生成的 UPN 的 TGT 被缓存,并可供其他了解 Kerberos 的应用程序使用,例如使用客户端端 Kerberos 认证插件的程序。在这种情况下,调用客户端时不指定用户名称或密码选项:
mysql --default-auth=authentication_kerberos_client --plugin-dir=*path/to/plugin/directory*客户端插件在缓存中找到 TGT,使用它获取 MySQL ST,并使用 ST 对 MySQL 服务器进行身份验证。
正如刚才描述的,当 UPN 的 TGT 被缓存时,在客户端命令中不需要用户名称和密码选项。如果命令仍然包含它们,则处理如下:
-
此命令包括一个用户名选项:
mysql --default-auth=authentication_kerberos_client --plugin-dir=*path/to/plugin/directory* --user=karl在这种情况下,如果选项指定的用户名与 TGT 中的 UPN 的用户名部分不匹配,则身份验证将失败。
-
此命令包括一个密码选项,在提示时输入:
mysql --default-auth=authentication_kerberos_client --plugin-dir=*path/to/plugin/directory* --password在这种情况下,客户端端插件会忽略密码。因为身份验证是基于 TGT 的,即使用户提供的密码不正确,也可以成功*。因此,如果找到导致密码被忽略的有效 TGT,插件会产生警告。
-
-
如果 Kerberos 缓存中不包含 TGT,则客户端端 Kerberos 认证插件本身可以从 KDC 获取 TGT。使用 MySQL 用户名和密码的选项调用客户端,然后在提示时输入 UPN 密码:
mysql --default-auth=authentication_kerberos_client --plugin-dir=*path/to/plugin/directory* --user=karl --password客户端端的 Kerberos 认证插件将用户名称(
karl)与用户帐户中指定的领域(MYSQL.LOCAL)结合起来构建 UPN(karl@MYSQL.LOCAL)。客户端插件使用 UPN 和密码获取 TGT,使用 TGT 获取 MySQL ST,并使用 ST 对 MySQL 服务器进行身份验证。或者,假设 Kerberos 缓存中不包含 TGT,并且命令指定了密码选项但没有用户名称选项:
mysql --default-auth=authentication_kerberos_client --plugin-dir=*path/to/plugin/directory* --password客户端端 Kerberos 认证插件使用操作系统登录名作为 MySQL 用户名。它将该用户名与用户的 MySQL 帐户中的领域结合起来构建 UPN。客户端插件使用 UPN 和密码获取 TGT,使用 TGT 获取 MySQL ST,并使用 ST 对 MySQL 服务器进行身份验证。
如果您不确定是否存在 TGT,可以使用klist进行检查。
注意
当客户端端 Kerberos 认证插件本身获取 TGT 时,客户端用户可能不希望 TGT 被重用。如用于 Kerberos 认证的客户端配置参数中所述,本地/etc/krb5.conf文件可用于使客户端插件在完成后销毁 TGT。
SSPI 模式下 Windows 客户端的连接命令
在 Windows 上,使用默认的客户端插件选项(SSPI),连接到 MySQL 服务器的适当客户端命令取决于命令是基于 MySQL 用户名和 UPN 密码的命令选项进行身份验证,还是使用 Windows 内存缓存中的 TGT。有关 Windows 上 GSSAPI 模式的详细信息,请参阅 GSSAPI 模式下 Windows 客户端的命令。
一个命令可以明确指定 MySQL 用户名和 UPN 密码的选项,也可以省略这些选项:
-
此命令包括 MySQL 用户名和 UPN 密码的选项:
mysql --default-auth=authentication_kerberos_client --plugin-dir=*path/to/plugin/directory* --user=karl --password客户端端的 Kerberos 认证插件将用户名称(
karl)和用户帐户中指定的领域(MYSQL.LOCAL)结合起来构建 UPN(karl@MYSQL.LOCAL)。客户端插件使用 UPN 和密码获取 TGT,使用 TGT 获取 MySQL ST,并使用 ST 对 MySQL 服务器进行身份验证。Windows 内存缓存中的任何信息都将被忽略;用户名称和密码选项值优先。
-
此命令包括 UPN 密码选项,但不包括 MySQL 用户名选项:
mysql --default-auth=authentication_kerberos_client --plugin-dir=*path/to/plugin/directory* --password客户端端的 Kerberos 认证插件使用已登录用户名称作为 MySQL 用户名,并将该用户名与用户 MySQL 帐户中的领域结合起来构建 UPN。客户端插件使用 UPN 和密码获取 TGT,使用 TGT 获取 MySQL ST,并使用 ST 对 MySQL 服务器进行身份验证。
-
此命令不包括 MySQL 用户名或 UPN 密码的选项:
mysql --default-auth=authentication_kerberos_client --plugin-dir=*path/to/plugin/directory*客户端端插件从 Windows 内存缓存中获取 TGT,使用 TGT 获取 MySQL ST,并使用 ST 对 MySQL 服务器进行身份验证。
这种方法要求客户端主机是 Windows Server Active Directory (AD) 域的一部分。如果不是这种情况,请通过手动输入 AD 服务器和领域作为 DNS 服务器和前缀来帮助 MySQL 客户端发现 AD 域的 IP 地址:
-
启动
console.exe并选择网络和共享中心。 -
从网络和共享中心窗口的侧边栏中,选择更改适配器设置。
-
在网络连接窗口中,右键单击要配置的网络或 VPN 连接,然后选择属性。
-
从网络选项卡中,找到并单击 Internet 协议版本 4 (TCP/IPv4),然后单击属性。
-
在 Internet 协议版本 4 (TCP/IPv4) 属性对话框中,单击高级。打开高级 TCP/IP 设置对话框。
-
从 DNS 选项卡中,将 Active Directory 服务器和领域添加为 DNS 服务器和前缀。
-
-
此命令包括 MySQL 用户名选项,但不包括 UPN 密码选项:
mysql --default-auth=authentication_kerberos_client --plugin-dir=*path/to/plugin/directory* --user=karl客户端端的 Kerberos 身份验证插件将由用户名称选项指定的名称与登录用户名进行比较。如果名称相同,则插件使用登录用户的 TGT 进行身份验证。如果名称不同,则身份验证失败。
在 GSSAPI 模式下的 Windows 客户端连接命令
在 Windows 上,客户端用户必须明确使用 plugin_authentication_kerberos_client_mode 插件选项指定 GSSAPI 模式,以通过 MIT Kerberos 库启用支持。默认模式为 SSPI(请参阅 SSPI 模式下 Windows 客户端的命令)。
可以指定 GSSAPI 模式:
-
在运行 Windows 主机上始终从 MIT Kerberos 缓存中检索或放置票证。
[mysql] plugin_authentication_kerberos_client_mode=GSSAPI或:
[mysql] plugin-authentication-kerberos-client-mode=GSSAPI -
在运行时从命令行使用 mysql 或 mysqldump 客户端程序。例如,以下命令(带有下划线或破折号)使 mysql 通过 MIT Kerberos 库连接到 Windows 上的服务器。
mysql *[connection-options]* --plugin_authentication_kerberos_client_mode=GSSAPI或:
mysql *[connection-options]* --plugin-authentication-kerberos-client-mode=GSSAPI -
客户端用户可以从 MySQL Workbench 和一些 MySQL 连接器中选择
GSSAPI模式。在运行 Windows 的客户端主机上,您可以覆盖默认位置:-
通过设置
KRB5_CONFIG环境变量来配置 Kerberos 配置文件。 -
使用
KRB5CCNAME环境变量设置默认凭据缓存名称(例如,KRB5CCNAME=DIR:/mydir/)。
有关特定客户端插件信息,请参阅
dev.mysql.com/doc/文档。 -
连接到 MySQL 服务器的适当客户端命令因命令是使用 MIT Kerberos 缓存中的 TGT 进行身份验证,还是基于 MySQL 用户名称和 UPN 密码的命令选项而异。在 Windows 上通过 MIT 库支持的 GSSAPI 与 Linux 上的 GSSAPI 类似(请参阅 Linux 客户端命令),但有以下例外:
-
在运行 MySQL 客户端程序之前,在选项文件中。插件变量名称可以使用下划线或破折号:
-
kinit 在 Windows 上以具有狭窄权限和特定角色的功能帐户运行。客户端用户不知道 kinit 密码。有关概述,请参阅
docs.oracle.com/en/java/javase/11/tools/kinit.html。 -
如果客户端用户提供密码,MIT Kerberos 库在 Windows 上决定是使用密码还是依赖现有票证。
-
描述在用于 Kerberos 认证的客户端配置参数中的
destroy_tickets参数不受支持,因为 Windows 上的 MIT Kerberos 库不支持所需的 API 成员(get_profile_boolean)来从配置文件中读取其值。
用于 Kerberos 认证的客户端配置参数
本节仅适用于运行 Linux 的客户端主机,不适用于运行 Windows 的客户端主机。
注意
运行 Windows 的客户端主机,将authentication_kerberos_client客户端 Kerberos 插件设置为GSSAPI模式支持客户端配置参数,但 Windows 上的 MIT Kerberos 库不支持本节中描述的destroy_tickets参数。
如果在 MySQL 客户端应用程序调用时不存在有效的票证授予票证(TGT),应用程序本身可以获取并缓存 TGT。如果在 Kerberos 认证过程中,客户端应用程序导致 TGT 被缓存,任何添加的 TGT 在不再需要时可以通过设置适当的配置参数销毁。
authentication_kerberos_client客户端 Kerberos 插件读取本地的/etc/krb5.conf文件。如果该文件丢失或无法访问,将会出现错误。假设文件可访问,它可以包含一个可选的[appdefaults]部分,提供插件使用的信息。将信息放在该部分的mysql部分内。例如:
[appdefaults]
mysql = {
destroy_tickets = true
}
客户端插件在mysql部分识别这些参数:
destroy_tickets值指示客户端插件在获取和使用 TGT 后是否销毁 TGT。默认情况下,destroy_tickets为false,但可以设置为true以避免 TGT 重用。(此设置仅适用于由客户端插件创建的 TGT,不适用于由其他插件或外部 MySQL 创建的 TGT。)
在客户端主机上,可以使用客户端 keytab 文件来获取 TGT 和 TS 而无需提供密码。有关 keytab 文件的信息,请参阅web.mit.edu/kerberos/krb5-latest/doc/basic/keytab_def.html。
Kerberos 认证调试
AUTHENTICATION_KERBEROS_CLIENT_LOG环境变量用于启用或禁用 Kerberos 认证的调试输出。
注意
尽管AUTHENTICATION_KERBEROS_CLIENT_LOG中包含CLIENT,但同一环境变量也适用于服务器端插件以及客户端插件。
在服务器端,允许的值为 0(关闭)和 1(开启)。日志消息写入服务器错误日志,受服务器错误日志详细级别的影响。例如,如果您正在使用基于优先级的日志过滤,log_error_verbosity 系统变量控制详细程度,如第 7.4.2.5 节“基于优先级的错误日志过滤(log_filter_internal)”中所述。
在客户端,允许的值为 1 到 5,并写入标准错误输出。以下表格显示了每个日志级别值的含义。
| 日志级别 | 含义 |
|---|---|
| 1 或未设置 | 无日志记录 |
| 2 | 错误消息 |
| 3 | 错误和警告消息 |
| 4 | 错误、警告和信息消息 |
| 5 | 错误、警告、信息和调试消息 |