SpringBoot使用LdapTemplate从AD分页查询超1000条记录时Cookie为空
解决方案
1. 让LdapTemplate使用手动配置的上下文
你现在手动创建了LdapContext并设置了分页控件,但ldapTemplate.search()默认会用自己管理的上下文,根本没用到你配置的这个。必须改用带上下文参数的重载方法:
修改查询代码中的search调用:
// 替换原search方法,传入手动创建的ldapContext ldapTemplate.search(ldapContext, "", filter.encode(), new AbstractContextMapper<String>() { @Override protected String doMapFromContext(DirContextOperations ctx) { return ctx.getNameInNamespace(); } }).forEach(results::add);
2. 手动注册分页响应控件的解码器
JDK默认不会自动解码PagedResultsResponseControl,所以你拿不到响应控件。在创建LdapContext后,添加注册解码器的代码:
LdapContext ldapContext = (LdapContext) ldapTemplate.getContextSource().getReadOnlyContext(); // 注册响应控件解码器 ldapContext.addToEnvironment( "java.naming.ldap.control.response", "1.2.840.113556.1.4.319:com.sun.jndi.ldap.ctl.PagedResultsResponseControl" ); // 再设置分页请求控件 ldapContext.setRequestControls(new Control[] { new PagedResultsControl(1000, cookie, Control.CRITICAL) });
3. 优化上下文复用(可选)
没必要每次循环都创建新上下文,复用一个上下文重置控件即可,减少资源消耗:
LdapContext ldapContext = (LdapContext) ldapTemplate.getContextSource().getReadOnlyContext(); try { byte[] cookie = null; // 先注册解码器 ldapContext.addToEnvironment( "java.naming.ldap.control.response", "1.2.840.113556.1.4.319:com.sun.jndi.ldap.ctl.PagedResultsResponseControl" ); do { ldapContext.setRequestControls(new Control[] { new PagedResultsControl(1000, cookie, Control.CRITICAL) }); // 使用带上下文的search方法 ldapTemplate.search(ldapContext, "", filter.encode(), new AbstractContextMapper<String>() { @Override protected String doMapFromContext(DirContextOperations ctx) { return ctx.getNameInNamespace(); } }).forEach(results::add); // 获取分页Cookie Control[] controls = ldapContext.getResponseControls(); cookie = null; if (controls != null) { for (Control control : controls) { if (control instanceof PagedResultsResponseControl) { cookie = ((PagedResultsResponseControl) control).getCookie(); } } } } while (cookie != null && cookie.length > 0); } finally { ldapContext.close(); }
4. 检查搜索范围和AD配置
- 确认搜索范围是否正确:当前搜索路径是空字符串,可能只查了base节点,建议指定具体OU或者用
SearchControls设置SUBTREE_SCOPE:SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); // 把searchControls传入search方法 ldapTemplate.search(ldapContext, "", filter.encode(), searchControls, mapper); - 确认AD服务器分页功能开启:AD默认支持分页,但部分环境可能被管理员禁用,需要联系运维确认。
内容的提问来源于stack exchange,提问作者sergiopf
相关产品推荐
相关产品推荐

