[英]Fetching more than 1000 rows from Domino LDAP server using .NET Core 5 and Novell.Directory.Ldap.NETStandard
I want to fetch all the users from a large location of our Domino LDAP, around ~2000 users altogether.我想从我们的 Domino LDAP 的一个大位置获取所有用户,总共大约 2000 个用户。 Since .NET Core sadly doesn't have a platform independent LDAP library, I'm using Novell.Directory.Ldap.NETStandard with this POC:
由于 .NET Core 很遗憾没有独立于平台的 LDAP 库,因此我在此 POC 中使用Novell.Directory.Ldap.NETStandard :
var cn = new Novell.Directory.Ldap.LdapConnection();
cn.Connect("dc.internal", 389);
cn.Bind("user", "pw");
string filter = "location=MyLoc";
var result = cn.Search("", Novell.Directory.Ldap.LdapConnection.ScopeOne, filter, new string[] { Novell.Directory.Ldap.LdapConnection.AllUserAttrs }, typesOnly: false);
int count = 0;
while (result.HasMore()) {
var entry = result.Next();
count++;
Console.WriteLine(entry.Dn);
}
It prints me a lot of entries, but not all.它打印了很多条目,但不是全部。 When
count = 1000
I got an Size Limit Exceeded
exception.当
count = 1000
我收到了Size Limit Exceeded
异常。 I guess this is because I need to use some kind of pagination, so not all entries woult be returned in a single request.我想这是因为我需要使用某种分页,因此并非所有条目都将在单个请求中返回。 There are different questions like this or this one .
有像这样或这样的不同问题。 Both in Java, the .NET Core API seems somehow different.
在 Java 中,.NET Core API 似乎有些不同。
LdapSearchRequest
works in .NET CoreLdapSearchRequest
在 .NET Core 中是如何工作的byte[] resumeCookie = null;
LdapMessageQueue queue = null;
var searchReq = new LdapSearchRequest("", LdapConnection.ScopeOne, filter, new string[] { LdapConnection.AllUserAttrs },
LdapSearchConstraints.DerefNever, maxResults: 3000, serverTimeLimit: 0, typesOnly: false, new LdapControl[] { new SimplePagedResultsControl(size: 100, resumeCookie) });
var searchRequest = cn.SendRequest(searchReq, queue);
I'm trying to figure out how the Java examples can be used in .NET Core.我试图弄清楚如何在 .NET Core 中使用 Java 示例。 This looks good, however I can't figure out how to fetch the LDAP entries.
这看起来不错,但是我不知道如何获取 LDAP 条目。 I only get an message id.
我只得到一个消息 ID。 By looking into the source it seems that I'm on the right way, but they're using
MessageAgent
which cannot be used outside since it's internal sealed
. 通过查看来源,我似乎走在正确的道路上,但他们使用的是
MessageAgent
,由于它是internal sealed
,因此不能在外部使用。 This is propably the reason why searching for LdapRearchRequest
in the source code doesn't give many results.这大概是为什么在源代码中搜索
LdapRearchRequest
没有给出很多结果的原因。
SimplePagedResultsControlHandler
SimplePagedResultsControlHandler
var opts = new SearchOptions("", LdapConnection.ScopeOne, filter, new string[] { LdapConnection.AllUserAttrs });
// For testing purpose: https://github.com/dsbenghe/Novell.Directory.Ldap.NETStandard/issues/163
cn.SearchConstraints.ReferralFollowing = false;
var pageControlHandler = new SimplePagedResultsControlHandler(cn);
var rows = pageControlHandler.SearchWithSimplePaging(opts, pageSize: 100);
This throws a Unavaliable Cricital Extension
exception.这会引发
Unavaliable Cricital Extension
异常。 First I thought that this is an issue of the .NET port, which may doesn't support all the features of the original Java library yet.首先我认为这是.NET端口的问题,它可能还不支持原始Java库的所有功能。 It seems complete and according to further researches, it looks like to be an LDAP error code.
它看起来很完整,根据进一步的研究,它看起来像是一个 LDAP 错误代码。 So this must be something which has to be supported by the server, but is not supported by Domino.
所以这必须是服务器必须支持的东西,但 Domino 不支持。
I couldn't make at least one of those approachs work, but found another way: Cross platform support for the System.DirectoryServices.Protocols namespace was was added in .NET 5 .我无法使这些方法中的至少一种起作用,但找到了另一种方法: 在 .NET 5 中添加了对System.DirectoryServices.Protocols命名空间的跨平台支持。 This was missing for a long time in .NET Core and I guess this is the main reason why libraries like
Novell.Directory.Ldap.NETStandard
were ported to .NET Core - in times of .NET Core 1.x this was the only way I found to authenticate against LDAP wich works on Linux too.这在 .NET Core 中缺失了很长时间,我想这就是像
Novell.Directory.Ldap.NETStandard
这样的库被移植到 .NET Core 的主要原因——在 .NET Core 1.x 时代,这是唯一的方法我发现对 LDAP 进行身份验证也适用于 Linux。
After having a deeper look into System.DirectoryServices.Protocols
, it works well out of the box, even for ~2k users.在深入了解
System.DirectoryServices.Protocols
,它开箱即用,即使对于大约 2k 用户也是如此。 My basic POC class looks like this:我的基本 POC 类如下所示:
public class DominoLdapManager {
LdapConnection cn = null;
public DominoLdapManager(string ldapHost, int ldapPort, string ldapBindUser, string ldapBindPassword) {
var server = new LdapDirectoryIdentifier(ldapHost, ldapPort);
var credentials = new NetworkCredential(ldapBindUser, ldapBindPassword);
cn = new LdapConnection(server);
cn.AuthType = AuthType.Basic;
cn.Bind(credentials);
}
public IEnumerable<DominoUser> Search(string filter, string searchBase = "") {
string[] attributes = { "cn", "mail", "companyname", "location" };
var req = new SearchRequest(searchBase, filter, SearchScope.Subtree, attributes);
var resp = (SearchResponse)cn.SendRequest(req);
foreach (SearchResultEntry entry in resp.Entries) {
var user = new DominoUser() {
Name = GetStringAttribute(entry, "cn"),
Mail = GetStringAttribute(entry, "mail"),
Company = GetStringAttribute(entry, "companyname"),
Location = GetStringAttribute(entry, "location")
};
yield return user;
}
yield break;
}
string GetStringAttribute(SearchResultEntry entry, string key) {
if (!entry.Attributes.Contains(key)) {
return string.Empty;
}
string[] rawVal = (string[])entry.Attributes[key].GetValues(typeof(string));
return rawVal[0];
}
}
Example usage:用法示例:
var ldapManager = new DominoLdapManager("ldap.host", 389, "binduser", "pw");
var users = ldapManager.Search("objectClass=person");
Novell.Directory.Ldap.NETStandard
as the title saidNovell.Directory.Ldap.NETStandard
解决This doesn't solve my problem with the Novell.Directory.Ldap.NETStandard
library as the title suggested, yes.正如标题所建议的那样,这并不能解决我的
Novell.Directory.Ldap.NETStandard
库问题,是的。 But since System.DirectoryServices.Protocols
is a official .NET package maintained by Microsoft and the .NET foundation, this seems the better aproach for me.但是由于
System.DirectoryServices.Protocols
是由 Microsoft 和 .NET 基金会维护的官方 .NET 包,这对我来说似乎是更好的方法。 The foundation will take care to keep it maintained and compatible with further .NET releases.该基金会将注意保持其维护并与进一步的 .NET 版本兼容。 When I wrote the question, I was not aware of the fact that Linux support is added now.
当我写这个问题时,我不知道现在添加了 Linux 支持。
Don't get me wrong, I don't want to say that third packages are bad by design - that would be completely wrong.不要误会我的意思,我不想说第三个包在设计上很糟糕——那是完全错误的。 However, when I have the choice between a official package and a third party one, I think it makes sense to prefer the official one.
但是,当我在官方包和第三方包之间进行选择时,我认为更喜欢官方包是有道理的。 Except there would be a good reason against that - which is not the case here: The official package (which doesn't exist in the past) works better to solve this issue than the third party one.
除非有一个很好的理由反对——这里不是这样:官方包(过去不存在)比第三方包更能解决这个问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.