This is an automated email from the ASF dual-hosted git repository.
shreemaan-abhishek pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new 74af1287d9 docs: add ldap-auth-advanced plugin documentation (#13794)
74af1287d9 is described below
commit 74af1287d938d189204fd40537118a27e6413937
Author: Mohammad Izzraff Janius
<[email protected]>
AuthorDate: Fri Aug 7 15:25:31 2026 +0800
docs: add ldap-auth-advanced plugin documentation (#13794)
---
docs/en/latest/config.json | 1 +
docs/en/latest/plugins/ldap-auth-advanced.md | 283 +++++++++++++++++++++++++++
docs/zh/latest/config.json | 1 +
docs/zh/latest/plugins/ldap-auth-advanced.md | 283 +++++++++++++++++++++++++++
4 files changed, 568 insertions(+)
diff --git a/docs/en/latest/config.json b/docs/en/latest/config.json
index 1619e8000b..5fb645afa3 100644
--- a/docs/en/latest/config.json
+++ b/docs/en/latest/config.json
@@ -138,6 +138,7 @@
"plugins/hmac-auth",
"plugins/authz-casbin",
"plugins/ldap-auth",
+ "plugins/ldap-auth-advanced",
"plugins/opa",
"plugins/forward-auth",
"plugins/multi-auth",
diff --git a/docs/en/latest/plugins/ldap-auth-advanced.md
b/docs/en/latest/plugins/ldap-auth-advanced.md
new file mode 100644
index 0000000000..ca1cbac2fd
--- /dev/null
+++ b/docs/en/latest/plugins/ldap-auth-advanced.md
@@ -0,0 +1,283 @@
+---
+title: ldap-auth-advanced
+keywords:
+ - Apache APISIX
+ - API Gateway
+ - Plugin
+ - LDAP Authentication
+ - ldap-auth-advanced
+description: The ldap-auth-advanced Plugin authenticates users against an LDAP
directory using search-then-bind; with consumer_required disabled, users do not
need to be enumerated in APISIX.
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+<head>
+ <link rel="canonical" href="https://docs.api7.ai/hub/ldap-auth-advanced" />
+</head>
+
+## Description
+
+The `ldap-auth-advanced` Plugin adds LDAP authentication to a Route or a
Service. Unlike [`ldap-auth`](./ldap-auth.md), which binds with a DN assembled
from the Consumer configuration, this Plugin *searches* the directory for the
user first, then binds as the entry it found. When `consumer_required` is
disabled, users do not need to be enumerated in APISIX; with the default
`true`, each authenticated user must still map to a Consumer by its `user_dn`.
+
+On each request the Plugin:
+
+1. Reads the credentials from the `Proxy-Authorization` header, falling back
to `Authorization`.
+2. Searches `base_dn` for the entry whose `attribute` matches the supplied
username, then binds as that entry with the supplied password.
+3. Attaches a matching [Consumer](../terminology/consumer.md), unless
`consumer_required` is `false`.
+
+The credential header uses the scheme word given by `header_type`, which
defaults to `ldap` rather than `basic`, so the default expects `Authorization:
ldap <base64(username:password)>`. Set `header_type` to `basic` to accept
ordinary [basic access
authentication](https://en.wikipedia.org/wiki/Basic_access_authentication)
instead.
+
+The Plugin distinguishes two failure modes, so an outage is never reported as
a rejected credential:
+
+| Status | Cause |
+|--------|-------|
+| `401` | Missing, malformed, or rejected credentials; a username matching
more than one entry; or `consumer_required` is `true` and no Consumer matches.
Returned with a `WWW-Authenticate` header. |
+| `500` | LDAP transport, TLS, protocol, or server-side failures — for example
an unreachable directory, a failed user search, or a user bind rejected with a
result code other than `invalidCredentials` — as well as rejected `bind_dn`
credentials. |
+
+This Plugin uses [lua-resty-ldap](https://github.com/api7/lua-resty-ldap) to
connect to the LDAP server.
+
+## Attributes
+
+For Consumer:
+
+| Name | Type | Required | Default | Valid values | Description |
+|------|------|----------|---------|--------------|-------------|
+| user_dn | string | True | | | DN of the LDAP user bound to this Consumer,
for example `cn=Jane Doe,ou=users,dc=example,dc=org`. This field supports
storing the value in Secret Manager using the [APISIX
Secret](../terminology/secret.md) resource. |
+
+For Route:
+
+| Name | Type | Required | Default | Valid values | Description |
+|------|------|----------|---------|--------------|-------------|
+| ldap_uri | string | True | | | Address of the LDAP server as `host` or
`host:port`. When the port is omitted, `636` is used if `use_ldaps` is enabled
and `389` otherwise. |
+| base_dn | string | True | | | DN of the subtree searched for the user, for
example `ou=users,dc=example,dc=org`. |
+| attribute | string | False | cn | | User attribute matched against the
supplied username, for example `uid` or `sAMAccountName`. |
+| bind_dn | string | False | | | DN used to bind before searching for the
user. When unset, the search binds anonymously. |
+| ldap_password | string | False | | | Password for `bind_dn`. Required when
`bind_dn` is set. The password is encrypted with AES before being stored in
etcd. |
+| use_ldaps | boolean | False | false | | If true, connect over LDAPS.
Mutually exclusive with `use_starttls`. |
+| use_starttls | boolean | False | false | | If true, upgrade the connection
with StartTLS. Mutually exclusive with `use_ldaps`. |
+| ssl_verify | boolean | False | true | | If true, verify the LDAP server's
certificate. Requires `ssl_trusted_certificate` to be set in `config.yaml`, and
the host in `ldap_uri` to match the host in the server certificate. |
+| timeout | integer | False | 10000 | [1, 60000] | Socket timeout in
milliseconds. |
+| keepalive | boolean | False | true | | If true, return the connection to the
pool for reuse instead of closing it. |
+| keepalive_timeout | integer | False | 60000 | >= 1000 | Idle time in
milliseconds after which a pooled connection is closed. |
+| keepalive_pool_size | integer | False | 5 | >= 1 | Maximum number of
connections kept in the pool. |
+| keepalive_pool_name | string | False | | | Name of the connection pool. Set
this to keep connections that use different credentials in separate pools. |
+| size_limit | integer | False | 2 | >= 2 | Maximum number of entries the user
search may return. The login attribute is expected to be unique, so more than
one match is treated as ambiguous and rejected. |
+| time_limit | integer | False | 5 | >= 0 | Time limit of the search in
seconds. `0` uses the server default. |
+| consumer_required | boolean | False | true | | If true, reject the request
with `401` when no Consumer matches the authenticated user. |
+| header_type | string | False | ldap | ["ldap", "basic"] | Scheme word
expected in the credential header. |
+| realm | string | False | ldap | | Realm in the
[`WWW-Authenticate`](https://datatracker.ietf.org/doc/html/rfc7235#section-4.1)
response header returned with a `401 Unauthorized` response. |
+
+## Examples
+
+The examples below assume an LDAP directory under `dc=example,dc=org` that
contains a user `Jane Doe` with `uid` of `jdoe` and password `janesecret`.
+
+:::note
+
+You can fetch the `admin_key` from `config.yaml` and save it to an environment
variable with the following command:
+
+```bash
+admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed
's/"//g')
+```
+
+:::
+
+### Authenticate Against an LDAP Directory
+
+The following example shows the minimum configuration: search `base_dn` for a
matching `uid`, then bind as that user.
+
+Create a Route with `ldap-auth-advanced`:
+
+```shell
+curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
+ -H "X-API-KEY: ${admin_key}" \
+ -d '{
+ "id": "ldap-auth-advanced-route",
+ "uri": "/anything",
+ "plugins": {
+ "ldap-auth-advanced": {
+ "ldap_uri": "127.0.0.1:1389",
+ "base_dn": "ou=users,dc=example,dc=org",
+ "attribute": "uid",
+ "consumer_required": false
+ }
+ },
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "httpbin.org:80": 1
+ }
+ }
+ }'
+```
+
+Send a request with valid credentials:
+
+```shell
+curl -i "http://127.0.0.1:9080/anything" \
+ -H "Authorization: ldap $(echo -n 'jdoe:janesecret' | base64)"
+```
+
+You should receive an `HTTP/1.1 200 OK` response.
+
+Send a request without credentials:
+
+```shell
+curl -i "http://127.0.0.1:9080/anything"
+```
+
+You should receive an `HTTP/1.1 401 Unauthorized` response with the following
body:
+
+```text
+{"message":"Authorization required"}
+```
+
+The response also carries the challenge built from `realm`:
+
+```text
+WWW-Authenticate: ldap realm="ldap"
+```
+
+A request with a wrong password is rejected the same way.
+
+If your directory does not allow anonymous searches, bind with a service
account by adding `bind_dn` and `ldap_password`. The user is still
authenticated with their own bind:
+
+```json
+{
+ "ldap-auth-advanced": {
+ "ldap_uri": "127.0.0.1:1389",
+ "base_dn": "ou=users,dc=example,dc=org",
+ "attribute": "uid",
+ "bind_dn": "cn=admin,dc=example,dc=org",
+ "ldap_password": "adminpassword",
+ "consumer_required": false
+ }
+}
+```
+
+To accept standard basic authentication instead of the `ldap` scheme, set
`header_type` to `basic`. Clients can then use `curl -u jdoe:janesecret`.
+
+### Map LDAP Identities to Consumers
+
+Associating an LDAP identity with a Consumer lets APISIX apply per-Consumer
configuration, such as rate limits, and adds the `X-Consumer-Username` header
to the Upstream request. A Consumer is bound to one LDAP user with `user_dn`.
+
+Create a Consumer bound to a user:
+
+```shell
+curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
+ -H "X-API-KEY: ${admin_key}" \
+ -d '{
+ "username": "jane",
+ "plugins": {
+ "ldap-auth-advanced": {
+ "user_dn": "cn=Jane Doe,ou=users,dc=example,dc=org"
+ }
+ }
+ }'
+```
+
+Update the Route to require a Consumer by removing `consumer_required`, which
defaults to `true`:
+
+```shell
+curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
+ -H "X-API-KEY: ${admin_key}" \
+ -d '{
+ "id": "ldap-auth-advanced-route",
+ "uri": "/anything",
+ "plugins": {
+ "ldap-auth-advanced": {
+ "ldap_uri": "127.0.0.1:1389",
+ "base_dn": "ou=users,dc=example,dc=org",
+ "attribute": "uid"
+ }
+ },
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "httpbin.org:80": 1
+ }
+ }
+ }'
+```
+
+Send a request as `jdoe`:
+
+```shell
+curl "http://127.0.0.1:9080/anything" \
+ -H "Authorization: ldap $(echo -n 'jdoe:janesecret' | base64)"
+```
+
+You should see the Consumer identified in the Upstream request:
+
+```json
+{
+ "headers": {
+ "X-Consumer-Username": "jane",
+ ...
+ },
+ ...
+}
+```
+
+Users matching no Consumer are rejected with `401`, unless `consumer_required`
is set to `false`.
+
+### Connect over LDAPS
+
+Set `use_ldaps` to connect over LDAPS, or `use_starttls` to upgrade a
plaintext connection. The two are mutually exclusive and the configuration is
rejected if both are enabled.
+
+```shell
+curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
+ -H "X-API-KEY: ${admin_key}" \
+ -d '{
+ "id": "ldap-auth-advanced-route",
+ "uri": "/anything",
+ "plugins": {
+ "ldap-auth-advanced": {
+ "ldap_uri": "ldap.example.org",
+ "use_ldaps": true,
+ "ssl_verify": true,
+ "base_dn": "ou=users,dc=example,dc=org",
+ "attribute": "uid",
+ "consumer_required": false
+ }
+ },
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "httpbin.org:80": 1
+ }
+ }
+ }'
+```
+
+When the port is omitted from `ldap_uri`, `636` is used with `use_ldaps` and
`389` otherwise.
+
+`ssl_verify` is enabled by default. Verification requires
`ssl_trusted_certificate` in `config.yaml` to point at the CA that signed the
LDAP server certificate, and the host in `ldap_uri` to match the certificate. A
certificate that cannot be verified fails the request with `500`.
+
+## Delete Plugin
+
+To remove the `ldap-auth-advanced` Plugin, you can delete the corresponding
JSON configuration from the Plugin configuration. APISIX will automatically
reload and you do not have to restart for this to take effect.
+
+```shell
+curl "http://127.0.0.1:9180/apisix/admin/routes/ldap-auth-advanced-route" -X
PATCH \
+ -H "X-API-KEY: ${admin_key}" \
+ -d '{
+ "plugins": {}
+ }'
+```
diff --git a/docs/zh/latest/config.json b/docs/zh/latest/config.json
index b1cac9d240..5f1d682020 100644
--- a/docs/zh/latest/config.json
+++ b/docs/zh/latest/config.json
@@ -126,6 +126,7 @@
"plugins/feishu-auth",
"plugins/authz-casbin",
"plugins/ldap-auth",
+ "plugins/ldap-auth-advanced",
"plugins/opa",
"plugins/forward-auth",
"plugins/multi-auth",
diff --git a/docs/zh/latest/plugins/ldap-auth-advanced.md
b/docs/zh/latest/plugins/ldap-auth-advanced.md
new file mode 100644
index 0000000000..326bd9d7ab
--- /dev/null
+++ b/docs/zh/latest/plugins/ldap-auth-advanced.md
@@ -0,0 +1,283 @@
+---
+title: ldap-auth-advanced
+keywords:
+ - Apache APISIX
+ - API 网关
+ - Plugin
+ - LDAP Authentication
+ - ldap-auth-advanced
+description: ldap-auth-advanced 插件通过“先搜索后绑定”的方式在 LDAP 目录中认证用户;在关闭
consumer_required 时,无需在 APISIX 中逐个维护用户。
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+<head>
+ <link rel="canonical" href="https://docs.api7.ai/hub/ldap-auth-advanced" />
+</head>
+
+## 描述
+
+`ldap-auth-advanced` 插件可用于给路由或服务添加 LDAP 身份认证。与使用 Consumer 配置拼接 DN 后直接绑定的
[`ldap-auth`](./ldap-auth.md) 不同,该插件会先在目录中**搜索**用户,再以搜索到的条目进行绑定。在
`consumer_required` 设置为 `false` 时,无需在 APISIX 中逐个维护用户;使用默认值 `true` 时,认证通过的用户仍需通过
`user_dn` 匹配到对应的 Consumer。
+
+插件在每个请求中依次执行以下操作:
+
+1. 从 `Proxy-Authorization` 请求头中读取凭证,若不可用则回退到 `Authorization`。
+2. 在 `base_dn` 子树中搜索 `attribute` 与用户名匹配的条目,并使用请求中的密码以该条目进行绑定。
+3. 关联匹配的 [Consumer](../terminology/consumer.md),除非 `consumer_required` 设置为
`false`。
+
+凭证请求头使用 `header_type` 指定的认证方案关键字,其默认值为 `ldap` 而非 `basic`,即默认要求 `Authorization:
ldap <base64(username:password)>`。如需使用标准的 [basic
authentication](https://en.wikipedia.org/wiki/Basic_access_authentication),请将
`header_type` 设置为 `basic`。
+
+插件会区分以下两种失败场景,因此服务端故障不会被误判为凭证错误:
+
+| 状态码 | 原因 |
+|--------|------|
+| `401` | 凭证缺失、格式错误或被拒绝;用户名匹配到多个条目;或 `consumer_required` 为 `true` 但没有匹配的
Consumer。响应中会携带 `WWW-Authenticate` 请求头。 |
+| `500` | LDAP 传输、TLS、协议或服务端故障(例如目录不可达、用户搜索失败,或用户绑定被以 `invalidCredentials`
以外的结果码拒绝),以及 `bind_dn` 凭证被拒绝。 |
+
+该插件使用 [lua-resty-ldap](https://github.com/api7/lua-resty-ldap) 连接 LDAP 服务器。
+
+## 属性
+
+Consumer 端:
+
+| 名称 | 类型 | 必选项 | 默认值 | 有效值 | 描述 |
+|------|------|--------|--------|--------|------|
+| user_dn | string | 是 | | | 与该 Consumer 绑定的 LDAP 用户 DN,例如 `cn=Jane
Doe,ou=users,dc=example,dc=org`。该字段支持使用 [APISIX
Secret](../terminology/secret.md) 资源保存在密钥管理服务中。 |
+
+Route 端:
+
+| 名称 | 类型 | 必选项 | 默认值 | 有效值 | 描述 |
+|------|------|--------|--------|--------|------|
+| ldap_uri | string | 是 | | | LDAP 服务器地址,格式为 `host` 或 `host:port`。省略端口时,启用
`use_ldaps` 使用 `636`,否则使用 `389`。 |
+| base_dn | string | 是 | | | 搜索用户的子树 DN,例如 `ou=users,dc=example,dc=org`。 |
+| attribute | string | 否 | cn | | 与请求中用户名匹配的用户属性,例如 `uid` 或 `sAMAccountName`。 |
+| bind_dn | string | 否 | | | 搜索用户前用于绑定的 DN。未配置时使用匿名绑定进行搜索。 |
+| ldap_password | string | 否 | | | `bind_dn` 对应的密码。配置 `bind_dn` 时必填。该密码在存入
etcd 前使用 AES 加密。 |
+| use_ldaps | boolean | 否 | false | | 如果为 true,则使用 LDAPS 连接。与 `use_starttls`
互斥。 |
+| use_starttls | boolean | 否 | false | | 如果为 true,则通过 StartTLS 升级明文连接。与
`use_ldaps` 互斥。 |
+| ssl_verify | boolean | 否 | true | | 如果为 true,则校验 LDAP 服务器证书。此时需要在
`config.yaml` 中配置 `ssl_trusted_certificate`,并确保 `ldap_uri` 中的主机名与服务器证书中的主机名一致。 |
+| timeout | integer | 否 | 10000 | [1, 60000] | 套接字超时时间,单位为毫秒。 |
+| keepalive | boolean | 否 | true | | 如果为 true,则将连接放回连接池复用,而不是直接关闭。 |
+| keepalive_timeout | integer | 否 | 60000 | >= 1000 | 连接池中连接的空闲超时时间,单位为毫秒。 |
+| keepalive_pool_size | integer | 否 | 5 | >= 1 | 连接池中保持的最大连接数。 |
+| keepalive_pool_name | string | 否 | | |
连接池名称。当不同配置使用不同凭证时,可通过该字段将连接隔离到不同的连接池。 |
+| size_limit | integer | 否 | 2 | >= 2 |
用户搜索返回条目数的上限。登录属性应当唯一,因此匹配到多个条目会被视为歧义并拒绝。 |
+| time_limit | integer | 否 | 5 | >= 0 | 搜索的时间限制,单位为秒。`0` 表示使用服务器默认值。 |
+| consumer_required | boolean | 否 | true | | 如果为 true,当没有 Consumer 与认证用户匹配时,返回
`401` 拒绝请求。 |
+| header_type | string | 否 | ldap | ["ldap", "basic"] | 凭证请求头中期望的认证方案关键字。 |
+| realm | string | 否 | ldap | | 认证失败返回 `401 Unauthorized`
时,[`WWW-Authenticate`](https://datatracker.ietf.org/doc/html/rfc7235#section-4.1)
响应头中的 realm 值。 |
+
+## 示例
+
+以下示例假设 LDAP 目录位于 `dc=example,dc=org` 下,其中用户 `Jane Doe` 的 `uid` 为 `jdoe`、密码为
`janesecret`。
+
+:::note
+
+您可以通过以下命令从 `config.yaml` 中获取 `admin_key`,并将其保存到环境变量中:
+
+```bash
+admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed
's/"//g')
+```
+
+:::
+
+### 使用 LDAP 目录进行身份认证
+
+以下示例展示了最小配置:在 `base_dn` 中搜索 `uid` 匹配的用户,然后以该用户进行绑定。
+
+创建路由并启用 `ldap-auth-advanced` 插件:
+
+```shell
+curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
+ -H "X-API-KEY: ${admin_key}" \
+ -d '{
+ "id": "ldap-auth-advanced-route",
+ "uri": "/anything",
+ "plugins": {
+ "ldap-auth-advanced": {
+ "ldap_uri": "127.0.0.1:1389",
+ "base_dn": "ou=users,dc=example,dc=org",
+ "attribute": "uid",
+ "consumer_required": false
+ }
+ },
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "httpbin.org:80": 1
+ }
+ }
+ }'
+```
+
+使用正确的凭证发送请求:
+
+```shell
+curl -i "http://127.0.0.1:9080/anything" \
+ -H "Authorization: ldap $(echo -n 'jdoe:janesecret' | base64)"
+```
+
+您将会收到 `HTTP/1.1 200 OK` 响应。
+
+不携带凭证发送请求:
+
+```shell
+curl -i "http://127.0.0.1:9080/anything"
+```
+
+您将会收到 `HTTP/1.1 401 Unauthorized` 响应,响应体如下:
+
+```text
+{"message":"Authorization required"}
+```
+
+响应中同时会携带由 `realm` 生成的认证质询:
+
+```text
+WWW-Authenticate: ldap realm="ldap"
+```
+
+密码错误的请求也会以同样的方式被拒绝。
+
+如果目录不允许匿名搜索,可以添加 `bind_dn` 与 `ldap_password` 使用服务账号进行绑定。用户本身仍然通过自己的绑定完成认证:
+
+```json
+{
+ "ldap-auth-advanced": {
+ "ldap_uri": "127.0.0.1:1389",
+ "base_dn": "ou=users,dc=example,dc=org",
+ "attribute": "uid",
+ "bind_dn": "cn=admin,dc=example,dc=org",
+ "ldap_password": "adminpassword",
+ "consumer_required": false
+ }
+}
+```
+
+如需使用标准的 basic authentication 而非 `ldap` 方案,请将 `header_type` 设置为
`basic`,此后客户端即可使用 `curl -u jdoe:janesecret` 发送请求。
+
+### 将 LDAP 身份映射到 Consumer
+
+将 LDAP 身份与 Consumer 关联后,APISIX 可以应用针对该 Consumer 的配置(例如限流),并在转发给上游的请求中添加
`X-Consumer-Username` 请求头。Consumer 通过 `user_dn` 绑定到单个 LDAP 用户。
+
+创建绑定到单个用户的 Consumer:
+
+```shell
+curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
+ -H "X-API-KEY: ${admin_key}" \
+ -d '{
+ "username": "jane",
+ "plugins": {
+ "ldap-auth-advanced": {
+ "user_dn": "cn=Jane Doe,ou=users,dc=example,dc=org"
+ }
+ }
+ }'
+```
+
+更新路由,移除 `consumer_required` 使其恢复默认值 `true`,从而要求匹配 Consumer:
+
+```shell
+curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
+ -H "X-API-KEY: ${admin_key}" \
+ -d '{
+ "id": "ldap-auth-advanced-route",
+ "uri": "/anything",
+ "plugins": {
+ "ldap-auth-advanced": {
+ "ldap_uri": "127.0.0.1:1389",
+ "base_dn": "ou=users,dc=example,dc=org",
+ "attribute": "uid"
+ }
+ },
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "httpbin.org:80": 1
+ }
+ }
+ }'
+```
+
+以 `jdoe` 发送请求:
+
+```shell
+curl "http://127.0.0.1:9080/anything" \
+ -H "Authorization: ldap $(echo -n 'jdoe:janesecret' | base64)"
+```
+
+您将在转发给上游的请求中看到 Consumer 信息:
+
+```json
+{
+ "headers": {
+ "X-Consumer-Username": "jane",
+ ...
+ },
+ ...
+}
+```
+
+未匹配到任何 Consumer 的用户会被返回 `401`,除非将 `consumer_required` 设置为 `false`。
+
+### 通过 LDAPS 连接
+
+配置 `use_ldaps` 可以使用 LDAPS 连接,配置 `use_starttls` 则可以通过 StartTLS
升级明文连接。两者互斥,同时启用时配置会被拒绝。
+
+```shell
+curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
+ -H "X-API-KEY: ${admin_key}" \
+ -d '{
+ "id": "ldap-auth-advanced-route",
+ "uri": "/anything",
+ "plugins": {
+ "ldap-auth-advanced": {
+ "ldap_uri": "ldap.example.org",
+ "use_ldaps": true,
+ "ssl_verify": true,
+ "base_dn": "ou=users,dc=example,dc=org",
+ "attribute": "uid",
+ "consumer_required": false
+ }
+ },
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "httpbin.org:80": 1
+ }
+ }
+ }'
+```
+
+`ldap_uri` 省略端口时,启用 `use_ldaps` 使用 `636`,否则使用 `389`。
+
+`ssl_verify` 默认开启。此时需要在 `config.yaml` 中通过 `ssl_trusted_certificate` 配置签发 LDAP
服务器证书的 CA 证书,并确保 `ldap_uri` 中的主机名与证书一致。证书校验失败的请求会返回 `500`。
+
+## 删除插件
+
+当您需要禁用 `ldap-auth-advanced` 插件时,可以将对应的 JSON 配置从插件配置中删除,APISIX 将会自动重新加载,无需重启服务:
+
+```shell
+curl "http://127.0.0.1:9180/apisix/admin/routes/ldap-auth-advanced-route" -X
PATCH \
+ -H "X-API-KEY: ${admin_key}" \
+ -d '{
+ "plugins": {}
+ }'
+```