我希望从Domino LDAP的一个大位置获取所有用户,总共大约2000个用户。遗憾的是,由于LDAP没有独立于平台的LDAP库,所以我将Novell.Directory.Ldap.NETStandard与以下POC一起使用:
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);
}它打印了很多条目,但不是全部。当count = 1000时,我得到了一个Size Limit Exceeded异常。我猜这是因为我需要使用某种分页,所以不是所有的条目都会在一个请求中返回。有不同的问题,比如this或this one。在Java语言中,.NET核心API似乎有些不同。
方法1:尝试了解LdapSearchRequest在.NET核心中的工作原理
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);我正在尝试弄清楚如何在.NET核心中使用Java示例。这看起来不错,但是我不知道如何获取LDAP条目。我只得到一个消息id。By looking into the source看起来我走对了路,但是他们使用的是MessageAgent,因为它是internal sealed,所以不能在外面使用。这可能就是为什么在源代码中搜索LdapRearchRequest得不到太多结果的原因。
方法2:使用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);这会抛出一个Unavaliable Cricital Extension异常。首先,我认为这是.NET端口的问题,它可能还不支持原始Java库的所有功能。它看起来很完整,根据进一步的研究,它看起来像是一个LDAP错误代码。因此,这必须是服务器必须支持的东西,但Domino不支持。
发布于 2021-06-23 21:08:39
我无法使这些方法中的任何一种工作,但我找到了另一种方法:对System.DirectoryServices.Protocols名称空间的跨平台支持是was added in .NET 5。这在LDAP核心中缺失了很长一段时间,我猜这就是为什么像Novell.Directory.Ldap.NETStandard这样的库被移植到.NET核心中的主要原因--在LDAP核心1.x时代,这是我发现的唯一可以在.NET上工作的认证方式。
在深入研究System.DirectoryServices.Protocols之后,它开箱即用,即使对于大约2k用户也是如此。我的基本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];
}
}示例用法:
var ldapManager = new DominoLdapManager("ldap.host", 389, "binduser", "pw");
var users = ldapManager.Search("objectClass=person");但它并不像标题所说的那样用Novell.Directory.Ldap.NETStandard解决
是的,正如标题所示,这并没有解决我使用Novell.Directory.Ldap.NETStandard库的问题。但由于System.DirectoryServices.Protocols是由微软和.NET基金会维护的官方.NET包,这对我来说似乎是更好的方法。基金会将注意维护它,并与未来的.NET版本兼容。当我写这个问题的时候,我没有意识到现在增加了对Linux的支持。
不要误会我的意思,我不想说第三个包在设计上是糟糕的--那将是完全错误的。然而,当我可以在官方包和第三方包之间进行选择时,我认为选择官方包是有意义的。除非有一个很好的理由来反对这个问题--这里不是这样的:官方包(过去不存在)比第三方包更好地解决了这个问题。
https://stackoverflow.com/questions/68073791
复制相似问题