Paginate on LDAP server which does not support PagedResultsControl(在不支持 PagedResultsControl 的 LDAP 服务器上分页)
问题描述
我正在尝试使用 Spring LDAP(版本 2.3.2)获取 LDAP 服务器上的所有条目.在我的代码中,我使用 PagedResultsDirContextProcessor
对所有结果进行分页.这在支持 PagedResultsControl
的服务器上运行良好.
I'm trying to get all entries on an LDAP server using Spring LDAP (version 2.3.2). Within my code, I make use of PagedResultsDirContextProcessor
to paginate through all the result. This works fine on the servers which support PagedResultsControl
.
但是,我现在需要连接到不支持 PagedResultsControl
的 LDAP 服务器.如何在不使用 PagedResultsControl
的情况下获取所有条目?
However, I now need to connect to an LDAP server which does not support PagedResultsControl
. How can I get all entries without using PagedResultsControl
?
推荐答案
您可以通过 JNDI 使用 VirtualListView
.您必须检索并重新提供contextID"才能进行分页,如下所示:
You can use VirtualListView
via JNDI. You have to retrieve and re-supply the 'contextID' to paginate, as follows:
static final int LIST_SIZE = 20; // Adjust to suit
@Test
public void TestVLV() throws NamingException, IOException
{
Hashtable<String,Object> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=XXXXXXX");
env.put(Context.SECURITY_CREDENTIALS, "YYYYYYY");
try
{
/* Create initial context with no connection request controls */
LdapContext ctx = new InitialLdapContext(env, null);
/* Sort Control is required for VLV to work */
SortKey[] sortKeys =
{
// sort by cn
new SortKey("cn", true, "caseIgnoreOrderingMatch")
};
// Note: the constructors for SortControl that take String or String[]
// as the first argument produce 'no ordering rule' errors with OpenLDAP.
SortControl sctl = new SortControl(
// "cn",
// new String[]{"cn"},
sortKeys,
Control.CRITICAL);
/* VLV that returns the first 20 answers */
VirtualListViewControl vctl =
new VirtualListViewControl(1, 0, 0, LIST_SIZE-1, Control.CRITICAL);
/* Set context's request controls */
ctx.setRequestControls(new Control[]
{
sctl,
vctl
});
int count = 0;
SearchControls sc = new SearchControls(SearchControls.SUBTREE_SCOPE, 0, 0, null, false, false);
for (;;)
{
/* Perform search */
// System.out.println("namespace="+ctx.getNameInNamespace());
// System.out.println("count limit="+sc.getCountLimit());
// System.out.println("search scope="+sc.getSearchScope());
NamingEnumeration<SearchResult> ne =
ctx.search("ou=Users,dc=xxxx,dc=com", "(objectClass={0})", new String[]{"inetOrgPerson"}, sc);
/* Enumerate search results */
while (ne.hasMore())
{
count++;
SearchResult sr = ne.next();
// System.out.println(i+": "+sr.getName());
System.out.println(count+": "+sr.getNameInNamespace());
}
ne.close();
// Get the contextID.
Control[] controls = ctx.getResponseControls();
VirtualListViewResponseControl vlvrc = null;
byte[] contextID = null;
for (int j = 0; j < controls.length; j++)
{
if (controls[j] instanceof VirtualListViewResponseControl)
{
vlvrc = (VirtualListViewResponseControl)controls[j];
contextID = vlvrc.getContextID();
System.out.println("contextID=0x"+new BigInteger(1,contextID).toString(16));
if (contextID != null)
{
vctl = new VirtualListViewControl(vlvrc.getTargetOffset()+LIST_SIZE, 0, 0, LIST_SIZE-1, Control.CRITICAL);
vctl.setContextID(contextID);
ctx.setRequestControls(new Control[]
{
sctl,
vctl
});
}
break; // there should only be one VLV response control, and we're not interested in anything else.
}
}
if (vlvrc != null && contextID != null && count < vlvrc.getListSize())
{
System.out.println("Continuing");
}
else
{
System.out.println("Finished");
break;
}
}
ctx.close();
}
finally
{
}
}
当然,调整身份验证和搜索根目录和过滤器以适合自己.
Adjust the authentication and search root and filter to suit yourself, of course.
并测试它是否受支持(尽管上述代码中的不支持的关键控制"异常也会告诉您):
And to test whether it is supported (although an 'unsupported critical control' exception from the above code will tell you just as well):
/**
* Is VLV Control supported?
*
* Query the rootDSE object to find out if VLV Control is supported.
* @return true if it is supported.
*/
static boolean isVLVControlSupported(LdapContext ctx)
throws NamingException
{
String[] returningAttributes =
{
"supportedControl"
};
// Fetch the supportedControl attribute of the rootDSE object.
Attributes attrs = ctx.getAttributes("", returningAttributes);
Attribute attr = attrs.get("supportedControl");
System.out.println("supportedControls="+attr);
if (attr != null)
{
// Fast way to check. add() would have been just as good. Does no damage to the DIT.
return attr.remove(VLV_CONTROL_OID);
}
return false;
}
VirtualListViewControl
和 VirtualListViewResponseControl
是 Sun/Oracle LDAP Booster Pack 的一部分,您可以通过 Maven 获得:
The VirtualListViewControl
and VirtualListViewResponseControl
are part of the Sun/Oracle LDAP Booster Pack, which you can obtain via Maven as:
<dependency>
<groupId>com.sun</groupId>
<artifactId>ldapbp</artifactId>
<version>1.0</version>
<type>jar</type>
</dependency>
这篇关于在不支持 PagedResultsControl 的 LDAP 服务器上分页的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:在不支持 PagedResultsControl 的 LDAP 服务器上分页
基础教程推荐
- Java:带有char数组的println给出乱码 2022-01-01
- 减少 JVM 暂停时间 >1 秒使用 UseConcMarkSweepGC 2022-01-01
- Java Keytool 导入证书后出错,"keytool error: java.io.FileNotFoundException &拒绝访问" 2022-01-01
- “未找到匹配项"使用 matcher 的 group 方法时 2022-01-01
- 降序排序:Java Map 2022-01-01
- 无法使用修饰符“public final"访问 java.util.Ha 2022-01-01
- 设置 bean 时出现 Nullpointerexception 2022-01-01
- 在 Libgdx 中处理屏幕的正确方法 2022-01-01
- 如何使用 Java 创建 X509 证书? 2022-01-01
- FirebaseListAdapter 不推送聊天应用程序的单个项目 - Firebase-Ui 3.1 2022-01-01