使用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, '(&(objectclass=user)(memberOf={}))'.format(distinguished_name), attributes=["sAMAccountName"]) # 递归查询抛出错误 c.search(base, '(&(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, '(&(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
相关产品推荐
相关产品推荐

