python-ldap。从LDAP搜索中只检索几个条目。

问题描述 投票:1回答:3

我想模仿 ldapsearch -z 的标志行为,只从LDAP中检索特定数量的条目,使用 python-ldap.

然而,它一直失败,除了 SIZELIMIT_EXCEEDED.

有多个链接报告了这个问题,但建议的解决方案似乎并不奏效。

Python-ldap搜索。超出大小限制

LDAP: ldap.SIZELIMIT_EXCEED。

我使用的是 search_ext_s()sizelimit 参数设置为1,我相信这不会超过服务器的限制。

在Wireshark上,我看到有1个条目被返回,并且服务器引发了 SIZELIMIT_EXCEEDED. 这与 ldapsearch -z 行为

但是下面的一行引发了一个异常,我不知道如何检索返回的条目。

conn.search_ext_s(<base>,ldap.SCOPE_SUBTREE,'(cn=demo_user*)',['dn'],sizelimit=1)
ldap python-ldap
3个回答
1
投票

你必须使用异步搜索方法。LDAPObject.search_ext() 并将结果与 LDAPObject.result() 直到例外 ldap.SIZELIMIT_EXCEEDED 是提出的。


0
投票

根据评论中的讨论情况: 这就是我如何实现它。

import ldap

# These are not mandatory, I just have a habit
# of setting against Microsoft Active Directory

ldap.set_option(ldap.OPT_REFERRALS, 0)
ldap.set_option(ldap.OPT_PROTOCOL_VERSION, 3)

conn = ldap.initialize('ldap://<SERVER-IP>')
conn.simple_bind(<username>, <password>)

# Using async search version
ldap_result_id = conn.search_ext(<base-dn>, ldap.SCOPE_SUBTREE,
                                 <filter>, [desired-attrs],
                                 sizelimit=<your-desired-sizelimit>)
result_set = []
try:
  while 1:
    result_type, result_data = conn.result(ldap_result_id, 0)
    if (result_data == []):
      break
    else:
      # Handle the singular entry anyway you wish.
      # I am appending here
      if result_type == ldap.RES_SEARCH_ENTRY:
        result_set.append(result_data)
except ldap.SIZELIMIT_EXCEEDED:
  print 'Hitting sizelimit'

print result_set

采样输出。

# My server has about 500 entries for 'demo_user' - 1,2,3 etc.
# My filter is '(cn=demo_user*)', attrs = ['cn'] with sizelimit of 5

$ python ldap_sizelimit.py

Hitting sizelimit
[[('CN=demo_user0,OU=DemoUsers,DC=ad,DC=local', {'cn': ['demo_user0']})], 
[('CN=demo_user1,OU=DemoUsers,DC=ad,DC=local', {'cn': ['demo_user1']})], 
[('CN=demo_user10,OU=DemoUsers,DC=ad,DC=local', {'cn': ['demo_user10']})], 
[('CN=demo_user100,OU=DemoUsers,DC=ad,DC=local', {'cn': ['demo_user100']})], 
[('CN=demo_user101,OU=DemoUsers,DC=ad,DC=local', {'cn': ['demo_user101']})]]

你可以使用更多的srv控制来排序等,但我认为基本的想法是传达;)


0
投票

应允 如果你搜索的用户数少于服务器的大小限制所指定的数量,那么它就会起作用,但如果你希望收集的用户数超过这个数量,那么它就会失败 (AD 的默认值是 1000 个用户)。

这是一个Python3的实现,我在大量编辑了我所发现的东西之后,想出了一个Python3的实现。此处 并在 公文. 在写这篇文章的时候,它可以和pip3包一起工作。python-ldap 3.2.0版本。

def get_list_of_ldap_users():
    hostname = "google.com"
    username = "username_here"
    password = "password_here"
    base = "dc=google,dc=com"

    print(f"Connecting to the LDAP server at '{hostname}'...")
    connect = ldap.initialize(f"ldap://{hostname}")
    connect.set_option(ldap.OPT_REFERRALS, 0)
    connect.simple_bind_s(username, password)
    connect=ldap_server
    search_flt = "(cn=demo_user*)" # get all users with a specific cn
    page_size = 1 # how many users to search for in each page, this depends on the server maximum setting (default is 1000)
    searchreq_attrlist=["cn", "sn", "name", "userPrincipalName"] # change these to the attributes you care about
    req_ctrl = SimplePagedResultsControl(criticality=True, size=page_size, cookie='')
    msgid = connect.search_ext_s(base=base, scope=ldap.SCOPE_SUBTREE, filterstr=search_flt, attrlist=searchreq_attrlist, serverctrls=[req_ctrl])

    total_results = []
    pages = 0
    while True: # loop over all of the pages using the same cookie, otherwise the search will fail
        pages += 1
        rtype, rdata, rmsgid, serverctrls = connect.result3(msgid)
        for user in rdata:
            total_results.append(user)

        pctrls = [c for c in serverctrls if c.controlType == SimplePagedResultsControl.controlType]
        if pctrls:
            if pctrls[0].cookie: # Copy cookie from response control to request control
                req_ctrl.cookie = pctrls[0].cookie
                msgid = connect.search_ext_s(base=base, scope=ldap.SCOPE_SUBTREE, filterstr=search_flt, attrlist=searchreq_attrlist, serverctrls=[req_ctrl])
            else:
                break
        else:
            break
    return total_results
© www.soinside.com 2019 - 2024. All rights reserved.