Forward slashes in the names returned by JNDI quer

2019-05-05 19:14发布

问题:

I need to make several queries to LDAP directory server and I'm using JNDI directory facilities for it. Then I need to do some work with the objects from the query result using their distinguished names. Some of the entries returned by the server contain forward slash character, and because of this JNDI escapes the whole name with double quotes:

NamingEnumeration<SearchResult> results = dirContext.search(queryRoot, queryFilter, controls);
for (SearchResult result : Collections.list(results)) {
    String objectName = result.getName();
    System.out.println(objectName);
}

If one of the objects in the query results has a name, say, 'b=id/10,a=1', it is printed like this

"b=id/10,a=1"

Note the double quotes around the name. Because of these quotes I cannot create javax.naming.ldap.LdapName from it directly: it fails with NamingException "Invalid name".

I understand that I can remove these quotes manually, but this feels hacky. Is there a way to avoid such escaping? Or maybe there are cleaner methods to do what I need?

P.S. It is funny that official JNDI tutorial suggests using LdapName to achieve "easy name manipulation" and even mentions the escape problem but does not provide any links on the problem described above.

回答1:

If an AttributeValue has LDAP-specific syntax, the characters are converted (using the defined syntax specification) to UTF-8 and only the following characters must be escaped:

  • ' ' (space) at the beginning of the string
  • ' ' (space) at the end of the string
  • '"'
  • '+' (the plus character indicates a multi-valued RDN)
  • , (the comma character separates components of the distinguished name)
  • ;
  • <
  • >
  • \

The forward slash is a valid character and need not be escaped, therefore it must be handled by the application and the API used by that application. As you noted, the forward slash has "special meaning" to JNDI. JNDI is poorly designed in many respects, this is only one of the many. Consider using the UnboundID LDAP SDK for new code.

For example, add the following entry:

dn: uid=abc/def,ou=people,dc=example,dc=com
objectClass: top
objectClass: person
objectClass: inetOrgPerson
uid: abc/def
cn: abc/def
sn: abc/def
userPassword: this entry is used to test http://stackoverflow.com/questions/11690529/forward-slashes-in-the-names-returned-by-jndi-query-to-ldap-server

retrieve the entry just added:

ldapsearch -h localhost -p 10389 -D 'cn=RootDn'  -b dc=example,dc=com -s sub '(uid=abc/def)' 1.1
Enter bind password: 
version: 1
dn: uid=abc/def,ou=people,dc=example,dc=com

see also

  • string representation of distinguished names


回答2:

The search result return by SearchResult.getName() is of the form of CompositeName. Try to use it like this:

Name itemPart = new CompositeName(result.getName())
Name absoluteName = new LdapName(myBasePath).addAll(itemPart)
// or
String sAbsoluteName = ctx.composeName(new LdapName(myBasePath), itemPart)

Strange escaping will be removed from absoluteName.