扩展 MySQL 8.0  / 第 4 章 MySQL 插件 API  / 4.4 编写插件  / 4.4.9 编写认证插件  /  6.4.1.9 LDAP 可插拔身份验证

6.4.1.9 LDAP 可插拔身份验证

笔记

LDAP 可插入身份验证是 MySQL Enterprise Edition 中包含的扩展,这是一种商业产品。要了解有关商业产品的更多信息,请参阅https://www.mysql.com/products/

从 MySQL 5.7.19 开始,MySQL Enterprise Edition 支持一种身份验证方法,使 MySQL Server 使用 LDAP(轻量级目录访问协议)通过访问 X.500 等目录服务来对 MySQL 用户进行身份验证。MySQL 使用 LDAP 获取用户、凭证和组信息。

LDAP 可插入身份验证提供以下功能:

  • 外部身份验证:LDAP 身份验证使 MySQL 服务器能够接受来自 LDAP 目录中 MySQL 授权表之外定义的用户的连接。

  • 代理用户支持:LDAP 身份验证可以根据外部用户所属的 LDAP 组向 MySQL 返回一个与客户端程序传递的外部用户名不同的用户名。这意味着 LDAP 插件可以返回定义外部 LDAP 身份验证用户应具有的权限的 MySQL 用户。例如,如果 LDAP 组为 ,则 名为的 LDAP 用户joe可以连接并拥有名为 的 MySQL 用户的权限 。 developerjoedeveloper

  • 安全性:使用 TLS,与 LDAP 服务器的连接可以是安全的。

下表显示了用于简单和基于 SASL 的 LDAP 身份验证的插件和库文件名。文件名后缀在您的系统上可能不同。这些文件必须位于 plugin_dir系统变量命名的目录中。

表 6.15 简单 LDAP 身份验证的插件和库名称

插件或文件 插件或文件名
服务器端插件名称 authentication_ldap_simple
客户端插件名称 mysql_clear_password
库文件名 authentication_ldap_simple.so

表 6.16 基于 SASL 的 LDAP 身份验证的插件和库名称

插件或文件 插件或文件名
服务器端插件名称 authentication_ldap_sasl
客户端插件名称 authentication_ldap_sasl_client
库文件名 authentication_ldap_sasl.so, authentication_ldap_sasl_client.so

库文件仅包含 身份验证插件。客户端 插件内置于 客户端库中。 authentication_ldap_XXXmysql_clear_passwordlibmysqlclient

每个服务器端 LDAP 插件都与特定的客户端插件一起工作:

  • 服务器端 authentication_ldap_simple插件执行简单的 LDAP 身份验证。对于使用此插件的帐户的连接,客户端程序使用客户端mysql_clear_password插件,该插件将密码以明文形式发送到服务器。没有使用密码散列或加密,因此建议在 MySQL 客户端和服务器之间建立安全连接以防止密码泄露。

  • 服务器端authentication_ldap_sasl 插件执行基于 SASL 的 LDAP 身份验证。对于使用此插件的帐户的连接,客户端程序使用客户端 authentication_ldap_sasl_client插件。客户端和服务器端 SASL LDAP 插件使用 SASL 消息在 LDAP 协议中安全传输凭证,以避免在 MySQL 客户端和服务器之间发送明文密码。

服务器端 LDAP 身份验证插件仅包含在 MySQL 企业版中。它们不包含在 MySQL 社区发行版中。客户端 SASL LDAP 插件包含在所有发行版中,包括社区发行版,并且如前所述,客户端 mysql_clear_password插件内置于 libmysqlclient客户端库中,客户端库也包含在所有发行版中。这使来自任何发行版的客户端都可以连接到加载了适当服务器端插件的服务器。

以下部分提供特定于 LDAP 可插入身份验证的安装和使用信息:

有关 MySQL 中可插入身份验证的一般信息,请参阅第 6.2.13 节,“可插入身份验证”。有关mysql_clear_password插件的信息,请参阅 第 6.4.1.6 节,“客户端明文可插入身份验证”。有关代理用户信息,请参阅第 6.2.14 节,“代理用户”

笔记

如果您的系统支持 PAM 并允许 LDAP 作为 PAM 身份验证方法,则使用 LDAP 进行 MySQL 用户身份验证的另一种方法是使用服务器端 authentication_pam插件。请参阅 第 6.4.1.7 节,“PAM 可插入身份验证”

LDAP 可插入身份验证的先决条件

要对 MySQL 使用 LDAP 可插入身份验证,必须满足以下先决条件:

  • LDAP 服务器必须可供 LDAP 身份验证插件与之通信。

  • 由 MySQL 认证的 LDAP 用户必须存在于 LDAP 服务器管理的目录中。

  • LDAP 客户端库必须在使用服务器端 authentication_ldap_saslauthentication_ldap_simple插件的系统上可用。目前,支持的库是 Windows 本地 LDAP 库,或非 Windows 系统上的 OpenLDAP 库。

  • 要使用基于 SASL 的 LDAP 身份验证:

    • LDAP 服务器必须配置为与 SASL 服务器通信。

    • SASL 客户端库必须在使用客户端 authentication_ldap_sasl_client 插件的系统上可用。目前,唯一受支持的库是 Cyrus SASL 库。

MySQL 用户的 LDAP 身份验证如何工作

本节概述了 MySQL 和 LDAP 如何协同工作来验证 MySQL 用户。有关显示如何设置 MySQL 帐户以使用特定 LDAP 身份验证插件的示例,请参阅 使用 LDAP 可插入身份验证

客户端连接到 MySQL 服务器,提供 MySQL 客户端用户名和 LDAP 密码:

  • 对于简单的 LDAP 身份验证,客户端和服务器端插件以明文形式传递密码。建议在 MySQL 客户端和服务器之间建立安全连接,以防止密码泄露。

  • 对于基于 SASL 的 LDAP 身份验证,客户端和服务器端插件避免在 MySQL 客户端和服务器之间发送明文密码。例如,插件可能使用 SASL 消息在 LDAP 协议中安全传输凭证。

如果客户端用户名和主机名均不匹配任何 MySQL 帐户,则连接被拒绝。

如果存在匹配的 MySQL 帐户,则会针对 LDAP 进行身份验证。LDAP 服务器查找与用户匹配的条目并根据 LDAP 密码验证该条目:

  • 如果 MySQL 帐户命名 LDAP 用户专有名称 (DN),则 LDAP 身份验证使用该值和客户端提供的 LDAP 密码。(要将 LDAP 用户 DN 与 MySQL 帐户相关联, 请在创建帐户 BY的语句中包含一个指定身份验证字符串的子句。)CREATE USER

  • 如果 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 身份验证插件。有关安装插件的一般信息,请参阅第 5.5.1 节,“安装和卸载插件”

要被服务器使用,插件库文件必须位于 MySQL 插件目录(由plugin_dir系统变量命名的目录)中。plugin_dir如有必要,通过在服务器启动时 设置值来配置插件目录位置 。

服务器端插件库文件的基本名称是 authentication_ldap_simpleauthentication_ldap_sasl. 文件名后缀因平台而异(例如, .so对于 Unix 和类 Unix 系统, .dll对于 Windows)。

要在服务器启动时加载插件,请使用 --plugin-load-add选项命名包含它们的库文件。使用这种插件加载方法,每次服务器启动时都必须给出选项。此外,为您希望配置的任何插件提供的系统变量指定值。

每个服务器端 LDAP 插件都公开了一组系统变量,可以配置其操作。设置其中大部分是可选的,但您必须设置指定 LDAP 服务器主机的变量(以便插件知道连接到哪里)和 LDAP 绑定操作的基本可分辨名称(以限制搜索范围并获得更快的搜索)。有关所有 LDAP 系统变量的详细信息,请参阅 第 6.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后重启服务器使新设置生效。

要验证插件安装,请检查 INFORMATION_SCHEMA.PLUGINS表格或使用SHOW PLUGINS 语句(请参阅 第 5.5.2 节,“获取服务器插件信息”)。例如:

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 的附加说明

在运行启用了 SELinux 的 EL6 或 EL 的系统上,需要更改 SELinux 策略才能使 MySQL LDAP 插件能够与 LDAP 服务进行通信:

  1. 创建一个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;
  2. 将安全策略模块编译成二进制表示:

    checkmodule -M -m mysqlldap.te -o mysqlldap.mod
  3. 创建 SELinux 策略模块包:

    semodule_package -m mysqlldap.mod  -o mysqlldap.pp
  4. 安装模块包:

    semodule -i mysqlldap.pp
  5. 更改 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 插件相关系统变量的启动选项。

LDAP 可插入身份验证和 ldap.conf

对于使用 OpenLDAP 的安装,该 ldap.conf文件提供了 LDAP 客户端的全局默认值。可以在此文件中设置选项以影响 LDAP 客户端,包括 LDAP 身份验证插件。OpenLDAP 按以下优先顺序使用配置选项:

  • LDAP 客户端指定的配置。

  • 文件中指定的配置 ldap.conf。要禁用此文件,请设置LDAPNOINIT 环境变量。

  • OpenLDAP 库内置默认值。

如果库默认值或ldap.conf 值未产生适当的选项值,则 LDAP 身份验证插件可能能够设置相关变量以直接影响 LDAP 配置。例如,LDAP 插件可以覆盖TLS 配置的参数:系统变量可用于启用 TLS 和 ldap.conf控制 CA 配置,例如 用于简单的 LDAP 身份验证, 以及 用于 SASL LDAP 身份验证。 authentication_ldap_simple_tlsauthentication_ldap_simple_ca_pathauthentication_ldap_sasl_tlsauthentication_ldap_sasl_ca_path

有关更多信息,ldap.conf 请参阅ldap.conf(5)手册页。

使用 LDAP 可插入身份验证

本节介绍如何使用 LDAP 可插入身份验证使 MySQL 帐户能够连接到 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 帐户相关联,请在创建帐户BY的语句中包含一个子句 CREATE USER。)如果帐户名称没有 LDAP 字符串,则 LDAP 身份验证使用客户端指定的用户名来查找 LDAP 条目。

  • 客户端程序使用适用于 MySQL 帐户使用的服务器端身份验证插件的连接方法进行连接。对于 LDAP 身份验证,连接需要 MySQL 用户名和 LDAP 密码。此外,对于使用服务器端 authentication_ldap_simple插件的帐​​户,调用带有 --enable-cleartext-plugin启用客户端 mysql_clear_password插件选项的客户端程序。

此处的说明假定以下场景:

  • MySQL 用户betsy和 分别向和 boris的 LDAP 条目进行身份验证。(MySQL 和 LDAP 用户名不一定不同。在此讨论中使用不同的名称有助于阐明操作上下文是 MySQL 还是 LDAP。) betsy_ldapboris_ldap

  • LDAP 条目使用该uid属性来指定用户名。这可能因 LDAP 服务器而异。某些 LDAP 服务器使用cn 用户名属性而不是 uid. 要更改属性,请适当修改 authentication_ldap_simple_user_search_attrauthentication_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

然后创建 MySQL 帐户的语句 betsy如下所示:

CREATE USER 'betsy'@'localhost'
  IDENTIFIED WITH authentication_ldap_simple
  AS 'uid=betsy_ldap,ou=People,dc=example,dc=com';

BY子句中指定的身份验证字符串不包括 LDAP 密码。这必须由客户端用户在连接时提供。

客户端通过提供 MySQL 用户名和 LDAP 密码并启用客户端 mysql_clear_password插件来连接到 MySQL 服务器:

$> mysql --user=betsy --password --enable-cleartext-plugin
Enter password: betsy_password (betsy_ldap LDAP password)
笔记

客户端mysql_clear_password 身份验证插件保持密码不变,因此客户端程序将其以明文形式发送到 MySQL 服务器。这使密码能够按原样传递到 LDAP 服务器。在没有 SASL 的情况下使用服务器端 LDAP 库需要明文密码,但在某些配置中可能会出现安全问题。这些措施将风险降至最低:

身份验证过程如下:

  1. 客户端插件将客户端用户名和 LDAP 密码发送到 MySQL 服务器 betsybetsy_password

  2. 连接尝试与 'betsy'@'localhost'帐户匹配。服务器端 LDAP 插件发现此帐户具有 'uid=betsy_ldap,ou=People,dc=example,dc=com' 用于命名 LDAP 用户 DN 的身份验证字符串。插件将此字符串和 LDAP 密码发送到 LDAP 服务器。

  3. LDAP 服务器找到 LDAP 条目 betsy_ldap和密码匹配,因此 LDAP 身份验证成功。

  4. LDAP 条目没有组属性,因此服务器端插件返回客户端用户名 ( betsy) 作为经过身份验证的用户。这与客户端提供的用户名相同,因此不会发生代理,客户端会话使用该 'betsy'@'localhost'帐户进行权限检查。

如果匹配的 LDAP 条目包含组属性,则该属性值将是经过身份验证的用户名,如果该值不同于betsy,则将发生代理。有关使用组属性的示例,请参阅 使用代理进行 LDAP 身份验证

如果该CREATE USER语句不包含BY指定 betsy_ldapLDAP 专有名称的子句,则身份验证尝试将使用客户端提供的用户名(在本例中为betsy)。在没有 LDAP 条目的情况下betsy,身份验证将失败。

基于 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

然后创建 MySQL 帐户的语句 boris如下所示:

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 协议内安全传输凭据,以避免在 LDAP 之间发送明文密码。 MySQL 客户端和服务器。

使用代理的 LDAP 身份验证

LDAP 身份验证插件支持代理,使用户能够作为一个用户连接到 MySQL 服务器,但承担不同用户的权限。本节描述基本的 LDAP 插件代理支持。LDAP 插件还支持组偏好和代理用户映射规范;请参阅 LDAP 身份验证组首选项和映射规范

此处描述的代理实现基于使用 LDAP 组属性值将使用 LDAP 进行身份验证的连接 MySQL 用户映射到定义不同权限集的其他 MySQL 帐户。用户不通过定义权限的帐户直接连接。相反,它们通过使用 LDAP 进行身份验证的默认代理帐户进行连接,以便所有外部登录都映射到拥有特权的代理 MySQL 帐户。使用代理帐户连接的任何用户都映射到这些代理 MySQL 帐户之一,这些帐户的权限决定了允许外部用户进行的数据库操作。

此处的说明假定以下场景:

  • LDAP 条目使用uidcn属性分别指定用户名和组值。要使用不同的用户和组属性名称,请设置适当的特定于插件的系统变量:

  • 这些 LDAP 条目在 LDAP 服务器管理的目录中可用,以提供唯一标识每个用户的可分辨名称值:

    uid=basha,ou=People,dc=example,dc=com,cn=accounting
    uid=basil,ou=People,dc=example,dc=com,cn=front_office

    在连接时,组属性值成为经过身份验证的用户名,因此它们命名为 accountingfront_office代理帐户。

  • 这些示例假定使用 SASL LDAP 身份验证。对简单的 LDAP 身份验证进行适当的调整。

创建默认代理 MySQL 帐户:

CREATE USER ''@'%'
  IDENTIFIED WITH authentication_ldap_sasl;

代理帐户定义没有用于命名 LDAP 用户 DN 的子句。因此: AS 'auth_string'

  • 当客户端连接时,客户端用户名将成为要搜索的 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安装了插件。有关说明,请参阅 第 6.4.1.10 节,“无登录可插入身份验证”。)有关保护代理帐户不被直接使用的替代方法,请参阅 防止直接登录到代理帐户

向代理帐户 PROXY授予每个代理帐户的权限:

GRANT PROXY
  ON 'accounting'@'localhost'
  TO ''@'%';
GRANT PROXY
  ON 'front_office'@'localhost'
  TO ''@'%';

使用mysql命令行客户端以basha.

$> mysql --user=basha --password
Enter password: basha_password (basha LDAP password)

身份验证发生如下:

  1. ''@'%'服务器使用客户端用户的默认代理帐户 验证连接 basha

  2. 匹配的 LDAP 条目是:

    uid=basha,ou=People,dc=example,dc=com,cn=accounting
  3. 匹配的 LDAP 条目具有组属性 cn=accounting,因此 accounting成为经过身份验证的代理用户。

  4. 经过身份验证的用户不同于客户端用户名 basha,结果 basha被视为 的代理 accounting,并 basha承担代理accounting帐户的特权。以下查询返回如下所示的输出:

    mysql> SELECT USER(), CURRENT_USER(), @@proxy_user;
    +-----------------+----------------------+--------------+
    | USER()          | CURRENT_USER()       | @@proxy_user |
    +-----------------+----------------------+--------------+
    | basha@localhost | accounting@localhost | ''@'%'       |
    +-----------------+----------------------+--------------+

这表明basha使用授予代理 accountingMySQL 帐户的权限,并且通过默认代理用户帐户进行代理。

现在basil改为连接:

$> mysql --user=basil --password
Enter password: basil_password (basil LDAP password)

的身份验证过程basil与之前描述的类似 basha

  1. ''@'%'服务器使用客户端用户的默认代理帐户 验证连接 basil

  2. 匹配的 LDAP 条目是:

    uid=basil,ou=People,dc=example,dc=com,cn=front_office
  3. 匹配的 LDAP 条目具有组属性 cn=front_office,因此 front_office成为经过身份验证的代理用户。

  4. 经过身份验证的用户不同于客户端用户名 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_officeMySQL 帐户的权限,并且通过默认代理用户帐户进行代理。

LDAP 身份验证组首选项和映射规范

使用代理的 LDAP 身份验证中所述,基本 LDAP 身份验证代理的工作原理是插件使用 LDAP 服务器返回的第一个组名作为 MySQL 代理用户帐户名。如果 LDAP 服务器返回多个组名,则此简单功能无法指定关于使用哪个组名的任何首选项,或指定组名以外的任何名称作为代理用户名。

从 MySQL 5.7.25 开始,对于使用 LDAP 身份验证的 MySQL 帐户,身份验证字符串可以指定以下信息以启用更大的代理灵活性:

  • 按优先顺序排列的组列表,以便插件使用列表中与 LDAP 服务器返回的组匹配的第一个组名。

  • 从组名到代理用户名的映射,这样组名在匹配时可以提供指定名称以用作代理用户。这提供了使用组名作为代理用户的替代方法。

考虑以下 MySQL 代理帐户定义:

CREATE USER ''@'%'
  IDENTIFIED WITH authentication_ldap_sasl
  AS '+ou=People,dc=example,dc=com#grp1=usera,grp2,grp3=userc';

ou=People,dc=example,dc=com身份验证字符串有一个以字符为前缀 的用户 DN 后缀 +。因此,如 LDAP 身份验证用户 DN 后缀中所述,完整的用户 DN 由指定的用户 DN 后缀加上作为 uid属性的客户端用户名构成。

认证字符串的剩余部分以 开头 #,表示组偏好和映射信息的开始。身份验证字符串的这一部分以 grp1, grp2, 的顺序列出组名grp3。LDAP 插件将该列表与 LDAP 服务器返回的一组组名称进行比较,以列表顺序查找与返回名称的匹配项。插件使用第一个匹配项,或者如果没有匹配项,则身份验证失败。

假设 LDAP 服务器返回组 grp3grp2grp7。LDAP 插件之所以使用 grp2,是因为它是匹配的身份验证字符串中的第一个组,即使它不是 LDAP 服务器返回的第一个组。如果 LDAP 服务器返回grp4, grp2, 和 grp1,插件使用 grp1即使grp2 也匹配。grp1优先级高于grp2因为它在身份验证字符串中较早列出。

假设插件找到组名匹配,它执行从该组名到 MySQL 代理用户名的映射,如果有的话。对于示例代理帐户,映射发生如下:

  • 如果匹配的组名是grp1grp3,则它们在身份验证字符串中分别与用户名 usera和相关联userc。该插件使用相应的关联用户名作为代理用户名。

  • 如果匹配的组名为grp2,则认证字符串中没有关联的用户名。该插件grp2用作代理用户名。

如果 LDAP 服务器返回 DN 格式的组,LDAP 插件会解析组 DN 以从中提取组名。

要指定 LDAP 组首选项和映射信息,这些原则适用:

  • #以前缀字符 开始身份验证字符串的组首选项和映射部分。

  • 组偏好和映射规范是一个或多个项目的列表,以逗号分隔。每个项目的形式都是 or 。项目应按组名称优先顺序列出。对于插件从 LDAP 服务器返回的一组组名中选择的组名,这两种语法在效果上有所不同,如下所示: group_name=user_namegroup_name

    • 对于指定为 (带有用户名)的项目,组名映射到用户名,该用户名用作 MySQL 代理用户名。 group_name=user_name

    • 对于指定为 group_name(没有用户名)的项目,组名用作 MySQL 代理用户名。

  • 要引用包含特殊字符(如空格)的组名或用户名,请用双引号 ( ") 字符将其括起来。例如,如果一个项目的组名和用户名是my group namemy user name,则必须使用引号将其写入组映射中:

    "my group name"="my user name"

    如果项目的组名和用户名是 my_group_nameand 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 后缀

从 MySQL 5.7.21 开始,LDAP 身份验证插件允许提供用户 DN 信息的身份验证字符串以+前缀字符开头:

  • 在没有+字符的情况下,身份验证字符串值将按原样处理,无需修改。

  • 如果身份验证字符串以 开头 +,插件将根据客户端发送的用户名以及身份验证字符串中指定的 DN(已+删除)构造完整的用户 DN 值。在构造的 DN 中,客户端用户名成为指定 LDAP 用户名的属性的值。这是 uid默认的;要更改属性,请修改相应的系统变量(authentication_ldap_simple_user_search_attrauthentication_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 的属性:uiduid=accounting,ou=People,dc=example,dc=com

前面示例中的帐户具有非空用户名,因此客户端始终使用与帐户定义中指定的名称相同的名称连接到 MySQL 服务器。如果帐户的用户名为空,例如使用 代理进行LDAP 身份验证中''@'%'描述的默认匿名代理帐户 ,则客户端可能会使用不同的用户名连接到 MySQL 服务器。但原理是一样的:如果认证字符串以 开头,则插件使用客户端发送的用户名和认证字符串一起构造用户DN。 +

LDAP 身份验证方法

LDAP 身份验证插件使用可配置的身份验证方法。适当的系统变量和可用的方法选择是特定于插件的:

有关每种允许方法的信息,请参阅系统变量描述。