You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LDAP分页搜索结果异常:仅返回单页数据且无响应控件

分析LDAP分页查询仅返回单页数据及控制台提示"No controls were sent from the server"的问题

你遇到的这两个核心问题其实是同一个逻辑错误导致的——分页控制的处理位置完全错了,咱们来一步步捋清楚:

核心问题1:为什么只返回单页数据?

你把获取分页响应控制、重置分页请求控制的代码,放到了遍历单条用户结果的while (answer.hasMoreElements())循环里面。这意味着你刚处理完当前页的第一个用户,就去更新了分页cookie和请求控制,直接干扰了当前页剩余结果的遍历流程,导致程序只能拿到当前页的所有数据后就终止,无法触发下一页的查询。

正确的逻辑应该是:先把当前页的所有用户结果完整遍历并处理完,再去处理分页响应、更新cookie、准备下一页的查询。

核心问题2:为什么每条用户记录都输出"No controls were sent from the server"?

LDAP服务器的分页响应控制(PagedResultsResponseControl)是在整个当前页的所有结果都返回完毕后才会发送给客户端的,而不是每返回一个用户就发一次。你在遍历每个用户时都调用ctx.getResponseControls(),这时候服务器还没返回分页控制,自然拿不到目标控制,就会输出那句提示。

修复后的代码片段

把分页相关的处理逻辑从用户遍历的while循环里移出来,放到do-while循环的末尾,也就是当前页结果全部处理完之后:

public void stupidSearch(String searchOptions) {
    String tempString = "";
    try {
        LdapContext ctx = new InitialLdapContext(env, null);
        // Activate paged results
        int pageSize = 20;
        byte[] cookie = null;
        ctx.setRequestControls(new Control[]{new PagedResultsControl(pageSize, Control.NONCRITICAL)});
        int total;

        // 注意:补充初始化SearchControls,原代码遗漏了这一步
        SearchControls searchCtls = new SearchControls();
        // Specify the attributes to return
        String returnedAtts[] = {"Name", "samAccountName", "mail", "UserAccountControl", "distinguishedName"};
        searchCtls.setReturningAttributes(returnedAtts);
        // Specify the search scope
        searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);

        // 省略searchFilter和searchBase的赋值逻辑(与原代码一致)
        String searchFilter = "";
        String searchBase = "";
        // ...(这里保留你原有的searchFilter和searchBase的判断逻辑)

        do {
            System.out.println(searchBase);
            // Search for objects using the filter
            NamingEnumeration<SearchResult> answer = ctx.search(searchBase, searchFilter, searchCtls);

            // Loop through the current page's search results
            while (answer.hasMoreElements()) {
                SearchResult sr = (SearchResult) answer.next();
                Attributes attrs = sr.getAttributes();

                // 保留你原有的用户属性处理逻辑
                tempString = attrs.get("distinguishedName").toString();
                tempString = tempString.substring(tempString.indexOf(",")+4);
                tempString = tempString.substring(0, tempString.indexOf(",DC="));
                String[] reverseString = tempString.split(",OU=");
                List<String> reverseList = Arrays.asList(reverseString);
                Collections.reverse(reverseList);
                tempString = "";
                for (String reverseString1: reverseString) {
                    tempString = tempString + "\\" + reverseString1;
                }
                tempString = tempString.substring(1);
                // 假设location是类成员变量
                location.add(tempString);
                
                String enableCheck = attrs.get("UserAccountControl").toString().replaceAll(".*: ", "");
                String isEnabled = isActive(enableCheck).toString();
                // 假设results1-4是类成员变量
                results1.add(attrs.get("Name").toString());
                results2.add(attrs.get("samAccountName").toString());
                results4.add(isEnabled);
                results3.add(attrs.get("mail") != null ? attrs.get("mail").toString() : "");
            }

            // 当前页结果处理完毕,再处理分页响应
            Control[] controls = ctx.getResponseControls();
            cookie = null;
            if (controls != null) {
                for (Control control : controls) {
                    if (control instanceof PagedResultsResponseControl) {
                        PagedResultsResponseControl prrc = (PagedResultsResponseControl) control;
                        total = prrc.getResultSize();
                        if (total != 0) {
                            System.out.println("***************** END-OF-PAGE " + "(total : " + total + ") *****************\n");
                        } else {
                            System.out.println("***************** END-OF-PAGE " + "(total: unknown) ***************\n");
                        }
                        cookie = prrc.getCookie();
                    }
                }
            } else {
                System.out.println("No controls were sent from the server");
            }

            // 准备下一页的分页请求
            if (cookie != null && cookie.length != 0) {
                ctx.setRequestControls(new Control[]{new PagedResultsControl(pageSize, cookie, Control.CRITICAL)});
            }

        } while (cookie != null && cookie.length != 0); // 避免空cookie导致的无限循环

        ctx.close();
    } catch (NamingException e) {
        System.out.println("Search error: " + e);
        System.exit(-1);
    } catch (IOException ex) {
        Logger.getLogger(ADData.class.getName()).log(Level.SEVERE, null, ex);
    }
}

额外注意事项

  • 补充了SearchControls的初始化代码,原代码遗漏这一步会触发空指针异常
  • 调整了循环终止条件,判断cookie != null && cookie.length != 0,避免部分LDAP服务器返回空cookie数组导致的无限循环
  • 修复了原代码中位于catch块外的日志语句,避免编译错误

内容的提问来源于stack exchange,提问作者acidrain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:29:33