分页搜索返回不正确的结果数量

时间:2018-01-05 10:22:44

标签: java ldap

尝试将页面结果控件实现到我的代码以超过1000个用户限制,但它只返回尽可能多的用户,因为我已将页面大小设置为(例如页面大小设置为20,它只会返回20个用户)。如果我将页面大小设置为超过1000,它仍将最大值为1000.

这是我目前的代码:

public void setupStupidConnection()
{   
String ldapURL = "ldap://myldapurl";
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
//set security credentials, note using simple cleartext authentication
env.put(Context.SECURITY_AUTHENTICATION,"simple");
env.put("com.sun.jndi.ldap.read.timeout", "10000");

env.put(Context.SECURITY_PRINCIPAL,"username");
env.put(Context.SECURITY_CREDENTIALS,"password");

//connect to my domain controller
env.put(Context.PROVIDER_URL,ldapURL);
}

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;

    //Specify the attributes to return
    String returnedAtts[]={"Name", "samAccountName", "mail", "UserAccountControl", "distinguishedName"};
    searchCtls.setReturningAttributes(returnedAtts);

    //Specify the search scope
    searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);

    //specify the LDAP search filter
    String searchFilter;
    if(!"".equals(search))
    {
        switch(searchOptions)
        {
            case "Starts with...":
               searchFilter = "(&(objectClass=user) (objectCategory=person) (CN=" + search + "*))";    
            break;
            case "Ends with...":
               searchFilter = "(&(objectClass=user) (objectCategory=person) (CN=*" + search + "))";
            break;
            case "Contains...":
               searchFilter = "(&(objectClass=user) (objectCategory=person) (CN=*" + search + "*))";
            break;
            case "Equals...":
               searchFilter = "(&(objectClass=user) (objectCategory=person) (CN=" + search + "))";
            break;
            default:
               searchFilter = "(&(objectClass=user) (objectCategory=person) (CN=" + search + "*))"; 
            break;
        }
    }
    else
    {
        searchFilter = "(&(objectClass=user) (objectCategory=person))";
    }

    //Specify the Base for the search
    String searchBase;
    switch(searchPath)
    {
        case "A":
            searchBase = "OU=Accounts1";
        break;
        case "B":
            searchBase = "OU=Accounts2";
        break;
        case "C":
            searchBase = "OU=Accounts3";
        break;
        case "D":
            searchBase = "OU=Accounts4";
        break;
        default:
            searchBase = "OU=Accounts1";
        break;
    }
do
{
    System.out.println(searchBase);
    // Search for objects using the filter
        NamingEnumeration<SearchResult> answer = ctx.search(searchBase, searchFilter, searchCtls);

        //Loop through the 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.add(tempString);

            String enableCheck = attrs.get("UserAccountControl").toString().replaceAll(".*: ", "");
            String isEnabled = isActive(enableCheck).toString();
            results1.add(attrs.get("Name").toString());
           // System.out.println(attrs.get("Name").toString());
            results2.add(attrs.get("samAccountName").toString());
            results4.add(isEnabled);

            if (attrs.get("mail") != null)
            {
                results3.add(attrs.get("mail").toString());
            }
            else
            {
                results3.add("");
            }

            Control[] controls = ctx.getResponseControls();

            if (controls != null) 
            {
              for (int i = 0; i < controls.length; i++) 
              {
                if (controls[i] instanceof PagedResultsResponseControl) 
                {
                  PagedResultsResponseControl prrc = (PagedResultsResponseControl) controls[i];
                  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");
            }
            // Re-activate paged results
            ctx.setRequestControls(new Control[] { new PagedResultsControl(
                pageSize, cookie, Control.CRITICAL) });
        } 
    } while (cookie != null);
    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);
}
 Logger.getLogger(ADData.class.getName()).log(Level.SEVERE, null, ex);
}

我改变了一些事情来隐藏一些公司数据。对于它返回的每个用户,它总是输出&#34;没有从服务器发送控件&#34;。

有什么可能导致它的想法吗?

1 个答案:

答案 0 :(得分:3)

您已使用Control.NONCRITICAL。来自documentation

  

criticality - 如果为true,则服务器必须遵守控件并返回pageSize指示的搜索结果或拒绝执行搜索。如果为false,则服务器无需遵守控制。

所以你基本上说你没关系它不尊重你的页面大小。如果您确实需要使用页面大小,请使用Control.CRITICAL - 但请注意,这可能会导致请求完全失败。

如果您不介意一次只接收1000个结果 ,则需要适当使用分页,设置服务器生成的cookie以检索后续页面。看起来你正试图通过第二次ctx.setRequestControls调用来做到这一点,但你的代码有点破碎:

  • 您的while (cookie != null)循环不在do块的末尾,所以我相信您实际上得到的代码相当于:

    while(answer.hasMoreElements())    {        ...    }    while(cookie!= null)    {        ctx.close();    }

  • 您没有再次执行搜索。我个人不希望将控件设置为自动执行新搜索。 (我已经很久没有使用过LDAP API了,但是我希望你需要调用ctx.search才能生效。)