You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python ldap3获取LDAP组递归用户失败求助

使用ldap3查询AD递归组成员时的LDAPAttributeError问题解决

问题场景

使用Python3 + ldap3 v2.9查询企业AD(LDAP)时,普通组及组成员查询功能正常,但使用LDAP_MATCHING_RULE_IN_CHAIN(OID:1.2.840.113556.1.4.1941)查询递归组成员时,抛出以下错误:

ldap3.core.exceptions.LDAPAttributeError: invalid attribute ExtensibleMatch: matchingRule

复现代码

import ldap3
import json  # 补充原代码遗漏的导入

s = ldap3.Server(host="<ldapServerAddress>", port=636, use_ssl=True, get_info=ldap3.ALL)
c = ldap3.Connection(s, user='<user>', password='<password>', client_strategy="SYNC", read_only=True)
c.bind()
base = '<baseDC>'

# 获取"MYGROUP"的distinguishedName
c.search(search_base=base, search_filter="(sAMAccountName=MYGROUP)", attributes=["distinguishedName"])
dj_son = json.loads(c.response_to_json())
distinguished_name = dj_son["entries"][0]["attributes"]["distinguishedName"]

# 普通查询正常执行
c.search(base, '(&amp;(objectclass=user)(memberOf={}))'.format(distinguished_name), attributes=["sAMAccountName"])

# 递归查询抛出错误
c.search(base, '(&amp;(objectclass=user)(memberOf:1.2.840.113556.1.4.1941:={}))'.format(distinguished_name), attributes=["sAMAccountName"])

已知前提

  • LDAP服务器支持LDAP_MATCHING_RULE_IN_CHAIN扩展匹配规则
  • 该规则未被服务器禁用
  • 已使用最新版本ldap3(v2.9)

解决方案

方案1:跳过本地过滤器解析

在search方法中添加raw=True参数,让ldap3直接将过滤器字符串传递给LDAP服务器,不进行本地解析验证:

# 修改后的递归查询代码
c.search(base, '(&amp;(objectclass=user)(memberOf:1.2.840.113556.1.4.1941:={}))'.format(distinguished_name), attributes=["sAMAccountName"], raw=True)

方案2:使用ldap3 Filter类构造过滤器

通过ldap3内置的Filter类构造扩展匹配过滤器,避免字符串解析问题:

import ldap3
from ldap3 import Filter
import json

s = ldap3.Server(host="<ldapServerAddress>", port=636, use_ssl=True, get_info=ldap3.ALL)
c = ldap3.Connection(s, user='<user>', password='<password>', client_strategy="SYNC", read_only=True)
c.bind()
base = '<baseDC>'

# 获取组的distinguishedName
c.search(search_base=base, search_filter="(sAMAccountName=MYGROUP)", attributes=["distinguishedName"])
dj_son = json.loads(c.response_to_json())
distinguished_name = dj_son["entries"][0]["attributes"]["distinguishedName"]

# 构造递归memberOf过滤器
recursive_memberof = Filter.create('memberOf:1.2.840.113556.1.4.1941:={}', distinguished_name)
# 组合用户过滤条件
final_filter = Filter.and_(Filter('objectclass=user'), recursive_memberof)

# 执行递归查询
c.search(base, final_filter, attributes=["sAMAccountName"])

原因说明

ldap3默认会对传入的过滤器字符串进行本地解析和格式验证,但memberOf:OID:=这种AD特有的扩展匹配语法,在ldap3的本地解析逻辑中无法被正确识别为合法的ExtensibleMatch结构,因此抛出错误。通过raw=True跳过本地解析,或者使用Filter类生成规范的过滤器对象,即可绕过这个问题。

内容的提问来源于stack exchange,提问作者Tjamat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 14:40:16