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

Python LDAP3查询conn.entries返回空结果问题排查求助

LDAP查询返回空集合的问题排查与修复

你的代码返回空集合主要有以下几个遗漏点:

1. 未校验绑定是否成功

调用conn.bind()后没有检查绑定结果,若用户名、密码错误或服务器地址不可达,绑定失败会导致后续查询无任何结果。必须先确认绑定成功再执行查询。

2. 搜索范围默认值不符合需求

ldap3的conn.search()默认搜索范围是BASE(仅查询指定的基DN条目本身)。如果你的目标条目不是基DN本身,或者需要递归搜索子节点,必须显式指定search_scope=SUBTREE。

3. 查询过滤器与目标属性不匹配

(objectClass=*)会匹配所有LDAP条目,但maxPwdAge是**domainDNS(域对象)或groupPolicyContainer(组策略对象)**的专属属性,用宽泛的过滤器不仅效率低,还可能找不到正确的目标条目。需要使用精准的过滤器定位包含目标属性的对象。

4. 对maxPwdAge的存储位置认知有误

maxPwdAge并非所有条目都具备,它属于域级密码策略的一部分,正确的查询目标有两个:

  • 域对象:即你的基DN DC=AA,DC=BB,DC=CC(objectClass为domainDNS)
  • 默认域策略:路径为CN=Default Domain Policy,CN=System,DC=AA,DC=BB,DC=CC

修正后的代码

from ldap3 import Server, Connection, Tls, SUBTREE
import ssl

# LDAP server connection settings
ldap_server = 'ldaps://SERVER_FQDN:636'
ldap_user = 'USERNAME'
ldap_password = 'PASSWORD'
ldap_base_dn = 'DC=AA,DC=BB,DC=CC'  # highest level in the domain

# Establish LDAPS connection
server = Server(ldap_server, use_ssl=True, tls=Tls(validate=ssl.CERT_NONE))
conn = Connection(server, user=ldap_user, password=ldap_password)

# 检查绑定状态,失败则输出错误并退出
if not conn.bind():
    print(f"绑定失败: {conn.result}")
    exit()

# 方式1:查询域对象,获取域级maxPwdAge
print("=== 域对象信息 ===")
conn.search(
    search_base=ldap_base_dn,
    search_filter='(objectClass=domainDNS)',
    attributes=['objectGUID', 'maxPwdAge', 'name'],
    search_scope=SUBTREE
)

if conn.entries:
    for entry in conn.entries:
        object_guid = entry.objectGUID.value
        # 将Windows File Time转换为秒(100纳秒为单位)
        max_pwd_age = entry.maxPwdAge.value / 10000000 if entry.maxPwdAge.value else None
        name = entry.name.value

        print("Object GUID:", object_guid)
        print("最大密码有效期(秒):", max_pwd_age)
        print("名称:", name)

# 方式2:查询默认域策略,获取密码策略详情
print("\n=== 默认域策略信息 ===")
policy_base_dn = f'CN=System,{ldap_base_dn}'
conn.search(
    search_base=policy_base_dn,
    search_filter='(&(objectClass=groupPolicyContainer)(cn=Default Domain Policy))',
    attributes=['objectGUID', 'displayName', 'gPCFileSysPath']
)

if conn.entries:
    for entry in conn.entries:
        print("Object GUID:", entry.objectGUID.value)
        print("策略名称:", entry.displayName.value)
        print("策略存储路径:", entry.gPCFileSysPath.value)

# 解绑连接
conn.unbind()

额外说明

  • maxPwdAge的值以100纳秒为单位,转换为秒时需除以10000000;若值为负数,代表密码永不过期。
  • 若环境使用自定义密码策略,需调整search_filter定位对应的组策略对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 15:27:43