Я использую библиотеку 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, что я не знаю, что это такое,Поэтому я думаю, что что-то упустил в моем запросе.Что там не так?