如何在LDAP服务器上使用大量用户进行分页搜索



我需要创建一个使用.NET Core在Linux上工作的LDAP客户端。我搜索了互联网,唯一支持.NET标准的库为novell.directory.ldap(开源,IEI -https://github.com/dsbenghe/novell.directory.ldap.ldap.netantastard(。目录服务库在Linux的.NET核心中没有支持。

我介绍了文档,并成功地创建了一个基本的LDAP客户端应用程序。

现在问题:我需要同步很多用户(10.000,200.000用户(,默认情况下,我的LDAP服务器具有最大大小的第1000页(我不想更改它(。我使用了VirtuallistControl来创建页面,并且对10K用户来说还可以。

对于200k用户,它崩溃了,错误53-不愿意在ldapsortControl响应上执行。Novell库需要一个LdapsortControl才能执行分页操作(用于索引(,我认为我的LDAP无法对200K进行排序。我使用的代码:

        int startIndex = 1;
        int contentCount = 0;
        int afterIndex = 10;
        int count = 0;
        do
        {
            LdapVirtualListControl ctrl = new LdapVirtualListControl(startIndex, 0, afterIndex, contentCount);
            LdapSortKey[] keys = new LdapSortKey[1];
            keys[0] = new LdapSortKey("sn");
            LdapSortControl sort = new LdapSortControl(keys, true);
            LdapSearchConstraints constraints = _ldapConnection.SearchConstraints;
            constraints.setControls(new LdapControl[] { ctrl, sort});
            _ldapConnection.Constraints = constraints;
            LdapSearchResults lsc = _ldapConnection.Search(searchBase, searchScope, searchFilter, attributes, typesOnly, cons);
            while (lsc.HasMore())
            {
                try
                {
                    LdapEntry nextEntry = lsc.Next();
                    Console.WriteLine( nextEntry.DN);
                }
                catch (LdapException e)
                {
                    Console.WriteLine($"Error: {e.LdapErrorMessage}");
                    //Exception is thrown, go for next entry
                    continue;
                }
            }
            LdapControl[] controls = lsc.ResponseControls;
            if (controls == null)
            {
                Console.Out.WriteLine("No controls returned");
            }
            else
            {
                foreach (LdapControl control in controls)
                {
                    if (control.ID == "2.16.840.1.113730.3.4.10")
                    {
                        LdapVirtualListResponse response = new LdapVirtualListResponse(control.ID, control.Critical, control.getValue());
                        startIndex += afterIndex + 1;
                        contentCount = response.ContentCount;
                        count += afterIndex;
                    }
                }
            }
            Console.WriteLine(i);
        } while (count <= contentCount);

文档很小,没有足够的信息,我不知道如何使用Novell库以更好的方式进行分页。这里是否有人使用Novell LDAP库,并且在分页方面有任何经验,也可以帮助我?我毁了

谢谢

要使用novell.directory.ldap进行分页查询。

ldapvirtuallistControl尊重LDAP排序请求控制的参数:VLV(虚拟列表视图(,即:

before:after:index:content_count

其中" "是您想在索引之前返回的项目数,"索引和" content_count "是服务器中项目的预期总数。如果您不知道,则必须将0用作值。

如果要通过" ldapsearch" CLI返回前5个元素,则必须使用:'0:4:1:0'和'0:4:5:0',对于后续五个。

LDAPVIRTUALLISTCONTROL拥有一个具有相同参数的构造函数,但顺序不同:

LdapVirtualListControl(int startIndex, int beforeCount, int afterCount, int contentCount)

个人,我使用此功能正确设置参数:

public static LdapSearchConstraints AddPagination(this LdapSearchConstraints constraints, int page,
            int pageSize)
{
    int startIndex = (page - 1) * pageSize;
    startIndex++;
    int beforeCount = 0;
    int afterCount = pageSize - 1;
    int contentCount = 0; //0 means that i don't know the total count
    var lvlc = new LdapVirtualListControl(startIndex, beforeCount, afterCount, contentCount);
    constraints.setControls(lvlc);
    return constraints;
}

之后,另一个问题需要您的注意:如果您要求一组数据,这些数据位于数据集结束后,您将收到数据集的第一个项目。

说明:

LDAP中存在的数据示例:
|1 |2 |3 |4 |
如果我们要求集合
________ |3 |4 |5 |&lt; - 5不存在
LDAP返回:
________ |3 |4 |1 |&lt; - 从开始

开始

要解决此问题,我在返回之前删除了超过的元素:

var lastIndex = (page * pageSize);
if (lastIndex > result.Total)
{
    var itemsToReturn = (int) (result.Total - (lastIndex - pageSize));
    if (itemsToReturn < 1)
    {
        items = new List<LdapQueryItem>();
    }
    else
    {
        items = items.Take(itemsToReturn).ToList();
    }
}   

最后,获取总数的功能(在searchResults.hasmore((方法之后执行(

protected int? GetTotal(LdapSearchResults searchResult)
{
    if (searchResult == null) {
       throw new ArgumentNullException(nameof(searchResult));
    }
    if (searchResult.ResponseControls != null && searchResult.ResponseControls.Any())
    {
        foreach (LdapControl control in searchResult.ResponseControls)
        {
            if (control.ID == "2.16.840.1.113730.3.4.10") // the id of the response control
            {
                LdapVirtualListResponse response =
                    new LdapVirtualListResponse(control.ID, control.Critical, control.getValue());
                return response.ContentCount;
            }
        }
    }
    return null;
}

您可以在这本书上获得更多的见解和信息:了解和部署LDAP目录服务

最新更新