Page LDAP запрос к AD в .NET Core с использованием Novell LDAP - PullRequest
0 голосов
/ 17 марта 2019

Я использую библиотеку Novell LDAP для выполнения запросов к Active Directory из приложения .NET Code.Большинство запросов выполняются успешно, но некоторые возвращают более 1000 результатов, от которых сервер AD отказывает.Поэтому я попытался выяснить, как публиковать запросы LDAP с помощью библиотеки Novell.Решение, которое я собрал, выглядит как

public IEnumerable<LdapUser> GetUsers() {
    this.Connect();

    try {
        var cntRead = 0;                            // Total users read.
        int? cntTotal = null;                       // Users available.
        var curPage = 0;                            // Current page.
        var pageSize = this._config.LdapPageSize;   // Users per page.

        this.Bind();

        this._logger.LogInformation("Searching LDAP users.");
        do {
            var constraints = new LdapSearchConstraints();

            // The following has no effect:
            //constraints.MaxResults = 10000;

            // Commenting out the following succeeds until the 1000th entry.
            constraints.setControls(GetListControl(curPage, pageSize));

            var results = this._connection.Search(
                this._config.LdapSearchBase,
                this.LdapSearchScope,
                this._config.LdapUsersFilter,
                this.LdapUserProperties,
                false,
                constraints);

            while (results.hasMore() && ((cntTotal == null) || (cntRead < cntTotal))) {
                ++cntRead;

                LdapUser user = null;

                try {
                    var result = results.next();
                    Debug.WriteLine($"Found user {result.DN}.");
                    user = new LdapUser() {
                        AccountName = result.getAttribute(this._config.LdapAccountAttribute)?.StringValue,
                        DisplayName = result.getAttribute(this._config.LdapDisplayNameAttribute)?.StringValue
                    };
                } catch (LdapReferralException) {
                    continue;
                }

                yield return user;
            }

            ++curPage;
            cntTotal = GetTotalCount(results);
        } while ((cntTotal != null) && (cntRead < cntTotal));
    } finally {
        this._connection.Disconnect();
    }
}

и использует следующие два вспомогательных метода:

private static LdapControl GetListControl(int page, int pageSize) {
    Debug.Assert(page >= 0);
    Debug.Assert(pageSize >= 0);
    var index = page * pageSize + 1;
    var before = 0;
    var after = pageSize - 1;
    var count = 0;
    Debug.WriteLine($"LdapVirtualListControl({index}, {before}, {after}, {count}) = {before}:{after}:{index}:{count}");
    return new LdapVirtualListControl(index, before, after, count);
}

private static int? GetTotalCount(LdapSearchResults results) {
    Debug.Assert(results != null);

    if (results.ResponseControls != null) {
        var r = (from c in results.ResponseControls
                 let d = c as LdapVirtualListResponse
                 where (d != null)
                 select (LdapVirtualListResponse) c).SingleOrDefault();
        if (r != null) {
            return r.ContentCount;
        }
    }

    return null;
}   

Установка constraints.MaxResults, похоже, не влияет на сервер AD.Если я не установлю LdapVirtualListControl, получение будет успешным до тех пор, пока не будет извлечена 1000-я запись.

Если я использую LdapVirtualListControl, операция завершится неудачно при первом вызове results.next() со следующим исключением:

System.Collections.Generic.KeyNotFoundException: The given key '76' was not present in the dictionary.
   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at Novell.Directory.Ldap.Utilclass.ResourcesHandler.getResultString(Int32 code, CultureInfo locale)
   at Novell.Directory.Ldap.LdapResponse.get_ResultException()
   at Novell.Directory.Ldap.LdapResponse.chkResultCode()
   at Novell.Directory.Ldap.LdapSearchResults.next()

Код https://github.com/dsbenghe/Novell.Directory.Ldap.NETStandard/blob/master/src/Novell.Directory.Ldap.NETStandard/Utilclass/ResultCodeMessages.cs предполагает, что это просто ошибка повторения, и реальная проблема заключается в том, что вызов завершается ошибкой с кодом ошибки 76, что я не знаю, что это такое,Поэтому я думаю, что что-то упустил в моем запросе.Что там не так?

1 Ответ

1 голос
/ 17 марта 2019

Я исправил это - в случае, если кто-то столкнется с этим:

После некоторых исследований в Интернете я обнаружил на https://ldap.com/ldap-result-code-reference-other-server-side-result-codes/#rc-virtualListViewError, что означает код ошибки 76 и что LdapVirtualListResponse содержит больше информации.В моем случае ошибка была https://ldap.com/ldap-result-code-reference-other-server-side-result-codes/#rc-sortControlMissing - поэтому кажется, что для подкачки требуется элемент управления сортировкой.Чтобы это исправить, я добавил

constraints.setControls(new[] {
    new LdapSortControl(new LdapSortKey("cn"), true),
    GetListControl(curPage, pageSize)
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...