mysql中的数据库用户与外部认证(LDAP)集成

11次阅读

mysql 8.0.13+需启用authentication_ldap_sasl插件实现LDAP认证,依赖OpenLDAP库和SASL,不支持LDAPS或匿名绑定;用户须用IDENTIFIED WITH…AS指定DN/UPN,plugin列值为该插件,authentication_String存DN而非密码。

mysql中的数据库用户与外部认证(LDAP)集成

MySQL 8.0+ 使用 authentication_ldap_sasl 插件连接 LDAP

MySQL 原生支持 LDAP 外部认证,但仅限于 MySQL 8.0.13 及以上版本,且必须启用 authentication_ldap_sasl 插件(不是旧版的 authentication_ldap_simple)。该插件依赖 OpenLDAP 客户端库和 SASL 机制,不支持纯 LDAPS 绑定或匿名绑定。

常见错误现象包括:Plugin 'authentication_ldap_sasl' is not loaded(未安装插件)、access denied for user 'xxx'@'%' (using password: YES)(LDAP 绑定失败但 MySQL 日志未明确提示)、或 MySQL 启动时报 Failed to initialize plugin 'authentication_ldap_sasl'(OpenLDAP 库缺失)。

  • 确认插件已安装:
    INSTALL PLUGIN authentication_ldap_sasl SONAME 'authentication_ldap_sasl.so';
  • 检查依赖:linux 上需安装 openldap-clientscyrus-sasl-plain(RHEL/centos)或 libsasl2-modulesdebian/ubuntu
  • MySQL 配置文件中必须设置:plugin_load_add = authentication_ldap_sasl.so,否则重启后插件丢失
  • LDAP 服务器需开放 389(LDAP)或 636(LDAPS)端口,且 MySQL 服务器能直连——NAT、防火墙、SELinux 均可能拦截

创建 LDAP 映射用户时必须指定 IDENTIFIED WITH authentication_ldap_sasl

MySQL 用户不能只靠 CREATE USER 指定密码;必须显式声明认证方式,并绑定 LDAP 属性。用户账户本身不存密码,仅作权限容器,实际校验由 LDAP 服务器完成。

典型误操作是漏写 AS 子句或写错 DN 格式,导致创建成功但登录始终失败。例如:CREATE USER 'alice'@'%' IDENTIFIED WITH authentication_ldap_sasl AS 'uid=alice,ou=people,dc=example,dc=com'; 中若 uid=alice 在 LDAP 中实际为 sAmaccountName=alice(AD 环境),则匹配失败。

  • AD 环境常用映射格式:AS 'CN=alice,CN=Users,DC=example,DC=com' 或使用 UPN:AS 'alice@example.com'(需 LDAP 服务器支持)
  • OpenLDAP 常用格式:AS 'uid=alice,ou=People,dc=example,dc=com',注意大小写敏感性和 OU 名称是否准确
  • 若 LDAP 支持组映射,可配合 authentication_ldap_saslldap_server 配置项 + ldap_group_search_attr 实现角色继承,但 MySQL 本身不自动同步组权限,仍需手动 GRANT
  • 测试映射是否有效:用 ldapsearch -x -H ldap://ldap.example.com -b "dc=example,dc=com" "(uid=alice)" 先验证 DN 可查

mysql.user 表中 pluginauthentication_string 字段含义易混淆

启用 LDAP 后,mysql.user 表中对应用户的 plugin 列值为 authentication_ldap_sasl,而 authentication_string 存储的是 LDAP DN(或 UPN)字符串,**不是密码哈希**。这个字段会被 MySQL 直接用于构造 LDAP BIND 请求。

容易踩的坑是:执行 ALTER USER ... IDENTIFIED BY 'xxx' 会覆盖 authentication_string 为密码哈希,导致 LDAP 认证失效;或者误以为清空 authentication_string 就能“禁用 LDAP”,实际会导致 Empty authentication string 错误。

  • 修改 LDAP 映射应使用:
    ALTER USER 'alice'@'%' IDENTIFIED WITH authentication_ldap_sasl AS 'uid=alice-new,ou=People,dc=example,dc=com';
  • 禁用 LDAP 认证需切换回本地认证:
    ALTER USER 'alice'@'%' IDENTIFIED WITH mysql_native_password BY 'newpass';
  • 不要直接 UPDATE mysql.user 修改 authentication_string,MySQL 不保证事务一致性,且可能跳过插件校验逻辑
  • 查询当前映射:
    select User, Host, plugin, authentication_string FROM mysql.user WHERE User = 'alice';

调试 LDAP 连接失败优先查 MySQL 错误日志与 ldapsearch 对比

MySQL 的 LDAP 插件日志非常简略,默认只在错误日志中输出 LDAP bind failedCannot contact LDAP server,无法定位是网络、证书、DN 还是权限问题。最可靠的方式是复现相同参数用命令行工具验证。

关键点在于:MySQL 插件使用的 LDAP 连接参数(如 ldap_server_hostldap_server_portldap_bind_base_dn)必须与 ldapsearch 命令完全一致,否则对比无意义。

  • 从 MySQL 配置中提取参数:SELECT * FROM performance_schema.variables_by_thread WHERE VARIABLE_NAME LIKE 'ldap%';(需开启相关 Performance Schema 表)
  • 等效 ldapsearch 命令示例(OpenLDAP):
    ldapsearch -x -H ldap://ldap.example.com:389 -D "cn=admin,dc=example,dc=com" -w 'adminpass' -b "dc=example,dc=com" "(uid=alice)"
  • 若用 LDAPS,确保 MySQL 配置了 ldap_ssl_ca 路径,且该 CA 文件对 MySQL 进程可读(常因 SELinux 或文件权限拒绝)
  • 开启插件调试日志(临时):SET GLOBAL log_error_verbosity = 3;,然后观察错误日志中是否有更细粒度的 SASL 协商失败信息

LDAP 认证链路长、环节多,任意一环(网络、TLS 证书、DN 格式、LDAP 服务端 ACL、MySQL 插件配置)出问题都会表现为“用户名或密码错误”。比起反复改 MySQL 配置,先用 ldapsearchtelnet ldap.example.com 389 把底层通路跑通,是最省时间的做法。

text=ZqhQzanResources