news 2026/9/14 14:13:33

Apache APISIX ldap-auth 插件实战指南:基于 LDAP 的 Basic 认证接入与源码级原理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Apache APISIX ldap-auth 插件实战指南:基于 LDAP 的 Basic 认证接入与源码级原理

Apache APISIX ldap-auth 插件实战指南:基于 LDAP 的 Basic 认证接入与源码级原理

【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisix

导读

ldap-auth是 Apache APISIX 内置的认证类插件,用于将路由或服务接入企业 LDAP 目录服务,让 API 调用方凭借 HTTP Basic 认证(用户名/密码)完成身份校验,并关联到 APISIX 的 Consumer 对象实现后续的鉴权与限流。读完本文,你将掌握ldap-auth的完整属性含义、Consumer 与 Route 的双层配置方法、TLS 加密与证书校验、Secret 托管user_dn的进阶用法,以及认证失败的各类错误返回与排查思路。

插件简介

ldap-auth可以为 Route 或 Service 添加 LDAP 认证能力。它结合 Consumer 对象使用:API 调用方通过 HTTP Basic 认证(Authorization: Basic base64(user:password))携带凭据,插件使用 lua-resty-ldap 与 LDAP 服务器建立连接并完成绑定(bind)认证。

从源码(apisix/plugins/ldap-auth.lua)可以看到该插件的元信息:

local _M = { version = 0.1, priority = 2540, type = 'auth', name = plugin_name, schema = schema, consumer_schema = consumer_schema }
  • type = 'auth':属于认证类插件,在插件执行链中位于鉴权、限流类插件之前;
  • priority = 2540:优先级较高(对比同为认证类的basic-auth为 2520),保证在网关流程早期完成身份识别;
  • 同时声明了面向 Route/Service 的schema与面向 Consumer 的consumer_schema两套配置结构。

工作原理

ldap-auth在 OpenResty 的rewrite阶段完成全部认证逻辑(apisix/plugins/ldap-auth.lua),核心流程分三步:

  1. 解析 Authorization 头:读取请求头Authorization,用正则Basic\s(.+)提取 Base64 密文并解码,按:拆出用户名与密码;
  2. LDAP 绑定认证:调用ldap.ldap_authenticate(username, password, ldapconf)向 LDAP 服务器发起绑定请求,凭据无效直接返回 401;
  3. 关联 Consumer:按uid 属性 + 用户名 + base_dn拼接出完整 DN(如cn=user01,ou=users,dc=example,dc=org),在已配置ldap-auth的 Consumer 中查找匹配项,命中后通过consumer_mod.attach_consumer把 Consumer 挂到请求上下文,供后续插件使用。
客户端请求 ──► rewrite 阶段 ├─ 提取 Authorization 头(缺失 → 401 Missing authorization) ├─ 解析 Basic 凭据(格式错误 → 401 Invalid authorization) ├─ ldap_authenticate 绑定认证(失败 → 401 Invalid user authorization) └─ 按 user_dn 关联 Consumer(未匹配 → 401 Invalid user authorization)

其中 LDAP 连接参数在源码中有明确默认值(apisix/plugins/ldap-auth.lua):

local ldapconf = { timeout = 10000, -- 连接超时,单位毫秒 start_tls = false, -- 默认不启用 STARTTLS 升级 ldap_host = ldap_host, ldap_port = ldap_port or 389, -- 未指定端口时默认 389 ldaps = conf.use_tls, -- 是否使用 LDAPS(即 TLS) tls_verify = conf.tls_verify, base_dn = conf.base_dn, attribute = conf.uid, keepalive = 60000, -- 连接池 keepalive 时长,单位毫秒 }

ldap_uri由核心工具函数core.utils.parse_addr解析(apisix/core/utils.lua),支持host:port、IPv4、带方括号的 IPv6(如[::1]:1389)等格式;省略端口时自动回退到 389。

属性(Attributes)详解

Consumer 侧配置

名称类型必填描述
user_dnstringTrueLDAP 客户端的用户 DN,例如cn=user01,ou=users,dc=example,dc=org。该字段支持通过 APISIX Secret 资源保存为密文引用

对应的consumer_schema校验要求user_dn必填(apisix/plugins/ldap-auth.lua)。

Route / Service 侧配置

名称类型必填默认值描述
base_dnstringTrueLDAP 服务器的 Base DN,例如ou=users,dc=example,dc=org
ldap_uristringTrueLDAP 服务器地址,例如localhost:1389
use_tlsbooleanFalsefalse设为true时使用 TLS(即 LDAPS)连接
tls_verifybooleanFalsefalse在启用use_tls后是否校验服务器证书;设为true时必须在config.yaml中配置ssl_trusted_certificate,并确保ldap_uri的主机名与服务器证书中的主机名一致
uidstringFalsecn用于匹配的 uid 属性名,如cnuid

Route 侧 schema 只强制要求base_dnldap_uri两个字段(apisix/plugins/ldap-auth.lua)。

两点值得注意:

  • uid 参与 DN 拼接:Consumer 的user_dn必须与uid=用户名,base_dn拼接结果一致才能命中。例如uid设为cn、用户名为user01base_dnou=users,dc=example,dc=org时,拼接出的 DN 即为cn=user01,ou=users,dc=example,dc=org。若 LDAP 目录使用uid属性作为 RDN,把uid配置为uid即可。
  • tls_verify 依赖全局证书配置:启用证书校验时,需要在config.yamldeployment.ssl段配置 CA 证书路径(conf/config.yaml.example):
deployment: ssl: # ssl_trusted_certificate: /path/to/ca-cert # 用于校验服务器证书的 PEM 格式 CA 证书

启用插件

第一步:创建 Consumer

先通过 Admin API 创建 Consumer 并启用ldap-auth插件。admin_key可从conf/config.yaml中提取并写入环境变量:

admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')
curl http://127.0.0.1:9180/apisix/admin/consumers -H "X-API-KEY: $admin_key" -X PUT -d ' { "username": "foo", "plugins": { "ldap-auth": { "user_dn": "cn=user01,ou=users,dc=example,dc=org" } } }'

第二步:在 Route 或 Service 上启用

在目标 Route 上启用插件并配置 LDAP 服务器信息:

curl http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -d ' { "methods": ["GET"], "uri": "/hello", "plugins": { "ldap-auth": { "base_dn": "ou=users,dc=example,dc=org", "ldap_uri": "localhost:1389", "uid": "cn" } }, "upstream": { "type": "roundrobin", "nodes": { "127.0.0.1:1980": 1 } } }'

同样的配置也可以挂到 Service 上(/apisix/admin/services),让该 Service 下所有 Route 统一继承认证能力。

使用示例

完成上述配置后,客户端携带 Basic 凭据访问即可通过认证:

curl -i -uuser01:password1 http://127.0.0.1:9080/hello
HTTP/1.1 200 OK ... hello, world

各类认证失败场景

1. 缺少 Authorization 头:

curl -i http://127.0.0.1:9080/hello
HTTP/1.1 401 Unauthorized ... {"message":"Missing authorization in request"}

此时响应还会附带WWW-Authenticate: Basic realm='.'头,提示客户端应使用 Basic 认证(apisix/plugins/ldap-auth.lua)。

2. 用户名不存在(LDAP 绑定失败):

curl -i -uuser:password1 http://127.0.0.1:9080/hello
HTTP/1.1 401 Unauthorized ... {"message":"Invalid user authorization"}

3. 密码错误:

curl -i -uuser01:passwordfalse http://127.0.0.1:9080/hello
HTTP/1.1 401 Unauthorized ... {"message":"Invalid user authorization"}

错误信息速查表

场景返回消息
缺少 Authorization 头Missing authorization in request
Authorization 头格式非法(非 Basic、Base64 解码失败、无密码)Invalid authorization in request
LDAP 绑定失败 / Consumer 未匹配Invalid user authorization
未配置任何 ldap-auth ConsumerMissing related consumer

源码级认证链路解析

凭据解析

extract_auth_header函数(apisix/plugins/ldap-auth.lua)负责解析 Basic 头:

  • Basic\s(.+)提取密文,非 Basic 格式返回Invalid authorization header format
  • ngx.decode_base64解码失败返回Failed to decode authentication header
  • :拆分,拆分结果少于 2 段(如只有用户名没有密码)返回拆分错误;
  • 用户名与密码两侧的空白字符会被剔除。

认证与 Consumer 关联

绑定成功后才进入 Consumer 关联阶段(apisix/plugins/ldap-auth.lua):

local user_dn = conf.uid .. "=" .. user.username .. "," .. conf.base_dn local consumer_conf = consumer_mod.plugin(plugin_name) if not consumer_conf then return 401, { message = "Missing related consumer" } end local consumers = consumer_mod.consumers_kv(plugin_name, consumer_conf, "user_dn") local consumer = consumers[user_dn] if not consumer then return 401, {message = "Invalid user authorization"} end consumer_mod.attach_consumer(ctx, consumer, consumer_conf)

这里体现了ldap-auth的一个设计特点:LDAP 只负责校验密码是否有效,具体哪个 DN 属于哪个 Consumer 由 APISIX 侧的 Consumer 配置决定。即使 LDAP 目录中存在某个用户,只要该 DN 没有预先登记为 Consumer,请求依然会被拒绝。这种「LDAP 校验 + 本地 Consumer 授权」的两段式模型,让认证与授权解耦,便于与consumer-restrictionlimit-count等插件组合使用。

进阶:TLS 加密连接

当 LDAP 服务器需要加密传输时,在 Route 配置中开启use_tls

{ "plugins": { "ldap-auth": { "base_dn": "ou=users,dc=example,dc=org", "ldap_uri": "test.com:1636", "uid": "cn", "use_tls": true } } }

若还要校验服务器证书,追加tls_verify: true,并在config.yaml中配置 CA 证书路径(见上文)。注意:

  • ldap_uri中的主机名必须与服务器证书的 CN/SAN 匹配,否则校验证书会失败;
  • use_tls走的是 LDAPS 端口(默认 636 类端口),与start_tls(明文端口上的 STARTTLS 升级)不同,插件源码中start_tls固定为false

进阶:用 Secret 托管 user_dn

Consumer 的user_dn支持 APISIX Secret 引用,避免在配置中明文暴露 DN 信息。测试用例(t/plugin/ldap-auth.t)展示了完整的 Vault 集成流程:

  1. 创建 Vault Secret 资源:
curl http://127.0.0.1:9180/apisix/admin/secrets/vault/test1 -H "X-API-KEY: $admin_key" -X PUT -d ' { "uri": "http://127.0.0.1:8200", "prefix": "kv/apisix", "token": "root" }'
  1. 向 Vault 写入密钥:
VAULT_TOKEN='root' VAULT_ADDR='http://0.0.0.0:8200' vault kv put kv/apisix/user01 user_dn="cn=user01,ou=users,dc=example,dc=org"
  1. Consumer 的user_dn使用密文引用:
{ "username": "user01", "plugins": { "ldap-auth": { "user_dn": "$secret://vault/test1/user01/user_dn" } } }

测试用例还覆盖了 token 走环境变量的方式("token": "$ENV://VAULT_TOKEN"),进一步避免敏感信息落盘(t/plugin/ldap-auth.t)。

删除插件

移除插件只需清空 Route 配置中的plugins字段。APISIX 会热加载新配置,无需重启即可生效:

curl http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -d ' { "methods": ["GET"], "uri": "/hello", "plugins": {}, "upstream": { "type": "roundrobin", "nodes": { "127.0.0.1:1980": 1 } } }'

测试验证

仓库自带的测试套件 t/plugin/ldap-auth.t 共 25 个用例,覆盖了插件的主要行为路径,可作为功能参考与回归验证:

  • schema 校验:Consumer 侧缺user_dn、Route 侧base_dn类型错误(传入数字)均会被拒绝;
  • 认证失败分支:缺 Authorization 头(401)、格式非法的 Basic 头(401 + 日志Invalid authorization header format)、Base64 无效(日志Failed to decode authentication header)、只有用户名无密码(日志Split authorization err);
  • 认证成功分支:合法凭据返回hello world,日志中出现find consumer user01
  • TLS 分支use_tlsuse_tls + tls_verify两种组合均有用例;
  • Secret 分支:Vault 密文引用与环境变量 token 两种方式均通过验证。

这些测试同时印证了本文描述的返回消息与日志关键字,排查线上问题时可直接对照。

小结

ldap-auth用一份简洁的配置把 LDAP 目录认证无缝接入 APISIX 网关:Route 侧声明 LDAP 服务器连接参数,Consumer 侧登记用户 DN,客户端只需携带标准 Basic 凭据即可访问受保护 API。结合 TLS 加密、证书校验与 Secret 托管能力,它能够满足企业级目录认证场景对安全性与可维护性的要求;两段式「LDAP 验证 + Consumer 授权」的模型也使其能自然融入 APISIX 的消费者管理生态,与限流、黑白名单等插件协同工作。

【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisix

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 14:09:24

免费开源版IDEA到底值不值得用?IntelliJ IDEA Community Edition详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 14:08:17

用Python批量获取网站标题:解析原理与并发提速实战

简介:“批量获取网站标题1.3”是一款面向开发者与网络数据分析人员的轻量级抓取工具,核心用途是批量采集网站标题,同时支持域名、IP和端口识别,并能在网页多次跳转时自动跟随重定向,减少人工逐个访问的繁琐操作。工具底…

作者头像 李华