PAM 可插拔身份验证是 MySQL 企业版(一种商业产品)中包含的扩展。要了解有关商业产品的更多信息,请参阅 https://www.mysqlserver.cn/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.19 PAM 身份验证的插件和库名
插件或文件 | 插件或文件名 |
---|---|
服务器端插件 | authentication_pam |
客户端插件 | mysql_clear_password |
库文件 | authentication_pam.so |
与服务器端 PAM 插件通信的客户端 mysql_clear_password
明文插件内置于 libmysqlclient
客户端库中,并包含在所有发行版中,包括社区发行版。在所有 MySQL 发行版中包含客户端明文插件,使任何发行版的客户端都可以连接到已加载服务器端 PAM 插件的服务器。
以下部分提供了特定于 PAM 可插拔身份验证的安装和使用信息:
有关 MySQL 中可插拔身份验证的常规信息,请参阅 第 8.2.17 节“可插拔身份验证”。有关 mysql_clear_password
插件的信息,请参阅 第 8.4.1.4 节“客户端明文可插拔身份验证”。有关代理用户的信息,请参阅 第 8.2.19 节“代理用户”。
本节概述了 MySQL 和 PAM 如何协同工作以对 MySQL 用户进行身份验证。有关显示如何设置 MySQL 帐户以使用特定 PAM 服务的示例,请参阅 使用 PAM 可插拔身份验证。
客户端程序和服务器进行通信,客户端向服务器发送客户端用户名(默认情况下为操作系统用户名)和密码。
客户端用户名是外部用户名。
对于使用 PAM 服务器端身份验证插件的帐户,相应的客户端插件是
mysql_clear_password
。此客户端插件不执行密码哈希,因此客户端以明文形式将密码发送到服务器。
服务器根据外部用户名和客户端连接的主机查找匹配的 MySQL 帐户。PAM 插件使用 MySQL 服务器传递给它的信息(例如用户名、主机名、密码和身份验证字符串)。当您定义使用 PAM 进行身份验证的 MySQL 帐户时,身份验证字符串包含:
PAM 服务名称,系统管理员可以使用该名称来引用特定应用程序的身份验证方法。单个数据库服务器实例可以与多个应用程序相关联,因此服务名称的选择留给 SQL 应用程序开发人员。
(可选)如果要使用代理,则需要从 PAM 组到 MySQL 用户名的映射。
该插件使用身份验证字符串中命名的 PAM 服务来检查用户凭据,并返回
'身份验证成功,用户名为
或user_name
''身份验证失败'
。密码必须适合 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 身份验证插件。有关安装插件的常规信息,请参阅 第 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
。
要验证插件安装,请检查 Information Schema PLUGINS
表或使用 SHOW PLUGINS
语句(请参阅 第 7.6.2 节“获取服务器插件信息”)。例如:
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 身份验证插件的方法取决于您安装它的方式:
如果您使用
--plugin-load-add
选项在服务器启动时安装了插件,请在不使用该选项的情况下重新启动服务器。如果您使用
INSTALL PLUGIN
语句在运行时安装了插件,则该插件在服务器重新启动后仍将保持安装状态。要卸载它,请使用UNINSTALL PLUGIN
:UNINSTALL PLUGIN authentication_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 组映射列表,则插件会从左到右检查列表中的每个
对,并尝试在分配给已验证用户的组的非 MySQL 目录中查找pam_group_name
=mysql_user_name
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-unix
PAM 服务,而为其他用户使用mysql-ldap
PAM 服务。
这些示例做出以下假设。如果您的系统设置不同,您可能需要进行一些调整。
登录名和密码分别是
antonio
和antonio_password
。请将它们更改为要进行身份验证的用户的相应值。PAM 配置目录为
/etc/pam.d
。PAM 服务名称对应于身份验证方法(在本讨论中为
mysql-unix
或mysql-ldap
)。要使用给定的 PAM 服务,您必须在 PAM 配置目录中设置一个具有相同名称的 PAM 文件(如果该文件不存在,则创建它)。此外,您必须在CREATE USER
语句的身份验证字符串中为使用该 PAM 服务进行身份验证的任何帐户命名 PAM 服务。
PAM 身份验证插件在初始化时检查服务器启动环境中是否设置了 AUTHENTICATION_PAM_LOG
环境变量。如果设置了,则该插件会将诊断消息记录到标准输出。根据服务器的启动方式,消息可能会出现在控制台或错误日志中。这些消息有助于调试当插件执行身份验证时发生的与 PAM 相关的问题。有关更多信息,请参阅 PAM 身份验证调试。
此身份验证方案使用 PAM 来检查根据操作系统用户名和 Unix 密码定义的外部用户,而不进行代理。允许连接到 MySQL 服务器的每个此类外部用户都应该有一个匹配的 MySQL 帐户,该帐户被定义为使用 PAM 身份验证通过传统的 Unix 密码存储进行身份验证。
传统的 Unix 密码使用 /etc/shadow
文件进行检查。有关与此文件相关的可能问题的信息,请参阅 PAM 身份验证访问 Unix 密码存储。
验证 Unix 身份验证是否允许使用用户名
antonio
和密码antonio_password
登录操作系统。通过创建一个名为
/etc/pam.d/mysql-unix
的mysql-unix
PAM 服务文件,将 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-unix
PAM 服务进行身份验证: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
操作系统用户已通过身份验证,具有授予给antonio
MySQL 用户的权限,并且没有发生代理。
客户端 mysql_clear_password
身份验证插件不会触及密码,因此客户端程序会将其作为明文发送到 MySQL 服务器。这使得密码可以按原样传递给 PAM。使用服务器端 PAM 库需要明文密码,但在某些配置中这可能是一个安全问题。以下措施可以最大限度地降低风险:
为了减少无意中使用
mysql_clear_password
插件的可能性,MySQL 客户端必须显式启用它(例如,使用--enable-cleartext-plugin
选项)。请参阅 第 8.4.1.4 节“客户端明文可插拔身份验证”。为了避免在启用
mysql_clear_password
插件的情况下暴露密码,MySQL 客户端应使用加密连接连接到 MySQL 服务器。请参阅 第 8.3.1 节“配置 MySQL 以使用加密连接”。
此身份验证方案使用 PAM 来检查根据操作系统用户名和 LDAP 密码定义的外部用户,而不进行代理。允许连接到 MySQL 服务器的每个此类外部用户都应该有一个匹配的 MySQL 帐户,该帐户被定义为通过 LDAP 使用 PAM 身份验证。
要为 MySQL 使用 PAM LDAP 可插拔身份验证,必须满足以下先决条件:
必须有一个 LDAP 服务器可供 PAM LDAP 服务与其通信。
要由 MySQL 进行身份验证的每个 LDAP 用户都必须存在于 LDAP 服务器管理的目录中。
另一种使用 LDAP 进行 MySQL 用户身份验证的方法是使用特定于 LDAP 的身份验证插件。请参阅 第 8.4.1.7 节“LDAP 可插拔身份验证”。
按如下方式配置 MySQL 以进行 PAM LDAP 身份验证:
验证 Unix 身份验证是否允许使用用户名
antonio
和密码antonio_password
登录操作系统。通过创建一个名为
/etc/pam.d/mysql-ldap
的mysql-ldap
PAM 服务文件,将 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-ldap
PAM 服务进行身份验证: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 组映射,将使用 PAM 进行身份验证的连接 MySQL 用户映射到定义了不同权限集的其他 MySQL 帐户。用户不直接通过定义权限的帐户进行连接。相反,他们通过使用 PAM 进行身份验证的默认代理帐户进行连接,以便所有外部用户都被映射到拥有权限的 MySQL 帐户。使用代理帐户连接的任何用户都将被映射到其中一个 MySQL 帐户,这些帐户的权限决定了允许外部用户执行的数据库操作。
此处显示的过程使用 Unix 密码身份验证。要改用 LDAP,请参阅 不使用代理用户的 PAM LDAP 身份验证 的早期步骤。
传统的 Unix 密码使用 /etc/shadow
文件进行检查。有关与此文件相关的可能问题的信息,请参阅 PAM 身份验证访问 Unix 密码存储。
验证 Unix 身份验证是否允许使用用户名
antonio
和密码antonio_password
登录操作系统。验证
antonio
是否是root
或users
PAM 组的成员。通过创建一个名为
/etc/pam.d/mysql-unix
的文件,将 PAM 设置为通过操作系统用户对mysql-unix
PAM 服务进行身份验证。文件内容取决于系统,因此请检查/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
和users
PAM 组中的外部用户分别映射到developer
和data_entry
MySQL 用户名。当您设置代理用户时,需要 PAM 服务名称后面的 PAM 组映射列表。否则,插件将无法判断如何执行从外部用户名到正确的代理 MySQL 用户名的映射。
注意如果您的 MySQL 安装中有匿名用户,则它们可能会与默认代理用户发生冲突。有关此问题的更多信息以及处理方法,请参阅 默认代理用户和匿名用户冲突。
创建代理帐户并授予每个帐户应具有的权限:
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
帐户。(这假设已安装该插件。有关说明,请参阅 第 8.4.1.9 节“无登录可插拔身份验证”。)有关防止代理帐户被直接使用的替代方法,请参阅 防止直接登录代理帐户。为代理帐户授予每个代理帐户的
PROXY
权限:GRANT PROXY ON 'developer'@'localhost' TO ''@''; GRANT PROXY ON 'data_entry'@'localhost' TO ''@'';
使用 mysql 命令行客户端以
antonio
的身份连接到 MySQL 服务器。$> mysql --user=antonio --password --enable-cleartext-plugin Enter password: antonio_password
服务器使用默认的
''@''
代理帐户对连接进行身份验证。antonio
的最终权限取决于antonio
是哪个 PAM 组的成员。如果antonio
是root
PAM 组的成员,则 PAM 插件会将root
映射到developer
MySQL 用户名并将该名称返回给服务器。服务器验证''@''
是否具有developer
的PROXY
权限并允许连接。以下查询将返回如下所示的输出:mysql> SELECT USER(), CURRENT_USER(), @@proxy_user; +-------------------+---------------------+--------------+ | USER() | CURRENT_USER() | @@proxy_user | +-------------------+---------------------+--------------+ | antonio@localhost | developer@localhost | ''@'' | +-------------------+---------------------+--------------+
这表明
antonio
操作系统用户已通过身份验证,具有授予给developer
MySQL 用户的权限,并且代理是通过默认代理帐户发生的。如果
antonio
不是root
PAM 组的成员,而是users
PAM 组的成员,则会发生类似的过程,但插件会将user
PAM 组成员身份映射到data_entry
MySQL 用户名并将该名称返回给服务器:mysql> SELECT USER(), CURRENT_USER(), @@proxy_user; +-------------------+----------------------+--------------+ | USER() | CURRENT_USER() | @@proxy_user | +-------------------+----------------------+--------------+ | antonio@localhost | data_entry@localhost | ''@'' | +-------------------+----------------------+--------------+
这表明
antonio
操作系统用户已通过身份验证,具有data_entry
MySQL 用户的权限,并且代理是通过默认代理帐户发生的。
客户端 mysql_clear_password
身份验证插件不会触及密码,因此客户端程序会将其作为明文发送到 MySQL 服务器。这使得密码可以按原样传递给 PAM。使用服务器端 PAM 库需要明文密码,但在某些配置中这可能是一个安全问题。以下措施可以最大限度地降低风险:
为了减少无意中使用
mysql_clear_password
插件的可能性,MySQL 客户端必须显式启用它(例如,使用--enable-cleartext-plugin
选项)。请参阅 第 8.4.1.4 节“客户端明文可插拔身份验证”。为了避免在启用
mysql_clear_password
插件的情况下暴露密码,MySQL 客户端应使用加密连接连接到 MySQL 服务器。请参阅 第 8.3.1 节“配置 MySQL 以使用加密连接”。
在某些系统上,Unix 身份验证使用密码存储,例如 /etc/shadow
,该文件通常具有受限的访问权限。这可能会导致基于 MySQL PAM 的身份验证失败。不幸的是,PAM 实现不允许区分 “无法检查密码”(例如,由于无法读取 /etc/shadow
)和 “密码不匹配。” 如果您正在使用 Unix 密码存储进行 PAM 身份验证,则可以使用以下方法之一启用从 MySQL 对其的访问:
假设 MySQL 服务器是从
mysql
操作系统帐户运行的,请将该帐户放入具有/etc/shadow
访问权限的shadow
组中。在
/etc/group
中创建一个shadow
组。在
/etc/group
中将mysql
操作系统用户添加到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 身份验证插件在初始化时检查是否设置了 AUTHENTICATION_PAM_LOG
环境变量。如果设置了,则插件会启用将诊断消息记录到标准输出的功能。这些消息可能有助于调试插件执行身份验证时出现的与 PAM 相关的问题。
设置 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 服务文件以禁用任意密码访问。