Java RootDSE中的SearchRequest

Java RootDSE中的SearchRequest,java,active-directory,ldap,unboundid-ldap-sdk,Java,Active Directory,Ldap,Unboundid Ldap Sdk,我必须使用以下功能从广告服务器查询用户: public List<LDAPUserDTO> getUsersWithPaging(String filter) { List<LDAPUserDTO> userList = new ArrayList<>(); try(LDAPConnection connection = new LDAPConnection(config.getHost(),config.getPort(),config.g

我必须使用以下功能从广告服务器查询用户:

public List<LDAPUserDTO> getUsersWithPaging(String filter)
{
    List<LDAPUserDTO> userList = new ArrayList<>();

    try(LDAPConnection connection = new LDAPConnection(config.getHost(),config.getPort(),config.getUsername(),config.getPassword()))
    {
        SearchRequest searchRequest = new SearchRequest("", SearchScope.SUB,filter, null);          
        ASN1OctetString resumeCookie = null;
        while (true)
        {
            searchRequest.setControls(
                    new SimplePagedResultsControl(100, resumeCookie));
            SearchResult searchResult = connection.search(searchRequest);
            for (SearchResultEntry e : searchResult.getSearchEntries())
            {
                LDAPUserDTO tmp = new LDAPUserDTO();
                tmp.distinguishedName = e.getAttributeValue("distinguishedName");
                tmp.name = e.getAttributeValue("name");
                userList.add(tmp);
            }

            LDAPTestUtils.assertHasControl(searchResult,
                    SimplePagedResultsControl.PAGED_RESULTS_OID);
            SimplePagedResultsControl responseControl =
                    SimplePagedResultsControl.get(searchResult);
            if (responseControl.moreResultsToReturn())
            {
                resumeCookie = responseControl.getCookie();
            }
            else
            {
                break;
            }
        }       
        return userList;
    } catch (LDAPException e) {
        logger.error(e.getExceptionMessage());
        return null;
    }


}
所有这些都会导致各种异常或空结果:

Caused by: LDAPSDKUsageException(message='A null object was provided where a non-null object is required (non-null index 0). 

2020-04-01 10:42:22,902 ERROR [de.dbz.service.LDAPService] (default task-1272) LDAPException(resultCode=32 (no such object), numEntries=0, numReferences=0, diagnosticMessage='0000208D: NameErr: DSID-03100213, problem 2001 (NO_OBJECT), data 0, best match of:
    ''
 ', ldapSDKVersion=4.0.12, revision=aaefc59e0e6d110bf3a8e8a029adb776f6d2ce28')

无法从RootDSE查询用户

使用域,或者如果需要在林中跨域查询用户,请使用全局编录(在不同端口上运行,而不是LDAP的默认389/636)

RootDSE仅包含元数据。可能应该在其他地方询问此问题以了解更多信息,但首先请阅读Microsoft的文档,例如:

例如:可以读取namingContexts属性,以查找您可能要为实际用户查询的其他上下文

也许可以从这篇漂亮的文章开始作为介绍:


所以,我真的花了很多时间在这方面。可以查询
RootDSE
,但这并不像人们想象的那么简单

我主要使用WireShark来查看他们的LDAP浏览器在做什么

结果发现我离得并不远:

如您所见,
baseObject
在这里是空的。 另外,还有一个附加控件,它带有OID和ASN.1字符串
308400000003020102

那么,这本可读性更强的《308400000003020102》到底做了什么

首先,我们把它解码成一些东西,我们可以阅读-在这种情况下,这将是
int2

在二进制文件中,这将为我们提供:
0 0 0 0 0 0 0 1 0

从文件中我们知道,我们有以下符号:

| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30    | 31    |
|---|---|---|---|---|---|---|---|---|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|-------|-------|
| x | x | x | x | x | x | x | x | x | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | SSFPR | SSFDS |
或者我们只是从文档中获取int值:

  • 1
    =
    SSFDS
    ->
    SERVER\u SEARCH\u FLAG\u DOMAIN\u SCOPE
  • 2
    =
    SSFPR
    ->
    SERVER\u SEARCH\u FLAG\u PHANTOM\u ROOT
因此,在我的示例中,我们有
SSFPR
,其定义如下:

对于AD DS,指示服务器搜索除 从属于搜索库的应用程序NC副本,甚至 如果未在服务器上实例化搜索库。对于AD LDS 行为相同,只是它还包括应用程序NC 搜索中的副本。对于AD DS和AD LDS,这将导致 要在所有NC副本(应用程序NC除外)上执行的搜索 在从属于搜索库的DC上持有的AD DS DC上。 这将启用诸如空字符串之类的搜索基,这将导致 用于搜索所有NC副本(应用程序除外)的服务器 其持有的AD DS DC上的NCs

NC
代表
命名上下文
,它们作为
操作属性
存储在
RootDSE
中,名称为
namingContexts

另一个值,
SSFDS
执行以下操作:

防止在搜索时生成连续引用 返回结果。这将执行与 LDAP\服务器\域\范围\ OID控件

因此,有人可能会问我为什么要这样做。事实证明,我有一个客户在一个DC下有几个子DC。如果我告诉搜索处理转介,执行时间相当长,因此这对我来说不是一个真正的选项。但当我关闭它时,我在定义
BaseDN成为我想要检索其成员的组

通过Softerra的LDAP浏览器中的
RootDSE
选项进行搜索要快得多,并且在不到一秒钟的时间内返回结果

我个人不知道为什么这要快得多-但是没有微软任何工具界面的
ActiveDirectory
对我来说是一种黑魔法。但坦率地说,这不是我的专业领域

最后,我得到了以下Java代码:

SearchRequest searchRequest = new SearchRequest("", SearchScope.SUB, filter, null); 
[...]
Control globalSearch = new Control("1.2.840.113556.1.4.1340", true, new ASN1OctetString(Hex.decode("308400000003020102")));

searchRequest.setControls(new SimplePagedResultsControl(100, resumeCookie, true),globalSearch);
[...]
使用的
Hex.decode()
如下:
org.bouncycastle.util.encoders.Hex


非常感谢Softerra的员工,他们或多或少地结束了我的广告之旅。

结果是有点正确,但有一个简单的选择,让LDAP为您完成工作-请参见我的答案。感谢您的时间和贡献:)
SearchRequest searchRequest = new SearchRequest("", SearchScope.SUB, filter, null); 
[...]
Control globalSearch = new Control("1.2.840.113556.1.4.1340", true, new ASN1OctetString(Hex.decode("308400000003020102")));

searchRequest.setControls(new SimplePagedResultsControl(100, resumeCookie, true),globalSearch);
[...]