LDAP查询不返回正确的数据从Active Directory [英] LDAP query doesn't return correct data from Active Directory

查看:915
本文介绍了LDAP查询不返回正确的数据从Active Directory的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我工作的一个工具,从AD获取用户信息并将它们导入到另一个系统。我们正在计划使用的objectSID作为唯一标识符,但我发现,由于某些原因,在LDAP结果的objectSID不匹配的Active Directory中。大部分的字节是相同的,但也有一些有不同的,有时LDAP结果具有更少的字节以外还有在公元。

的objectSID从用户AD:

十进制:[1,5,0,0,0,0,0,5,21,0,0,0,35,106,222,96,236,251 ,239,68,32,255,234,203,122,第4,0,0]
(十六进制):[01,05,00,00,00,00,00,05,15,00,00,00,23,6A,DE,60,EC,FB,EF,44,20,FF,EA,CB ,7A,04,00,00]
 

的objectSID通过LDAP结果相同的用户:

 十进制:[1,5,0,0,0,0,0,5,21,0,0,0,35,106,63,96,63,63 ,63,68,32,63,63,63,122,4,0,0]
(十六进制):[01,05,00,00,00,00,00,05,15,00,00,00,23,6A,3楼,60,3楼,3楼,3楼,44,20,3楼,3楼,3楼,7A,04,00,00]
 

它几乎好像超过128的任何值回来作为LDAP结果63 / 3F。对于其他用户,LDAP结果是丢失1个字节(问号):

 十六进制从AD:01 05 00 00 00 00 00 05 15 00 00 00 23 6A DE 60 EC FB EF 44 20 FF EA CB 88 04 00 00]
(十六进制)从LDAP:[01 05 00 00 00 00 00 05 15 00 00 00 23 6A 3F 60 3F 3F 3F 44 20 3F 3F 3F? 04 00 00]
 

下面是的code我使用的是做这些测试的主要部分。

 最后弦乐ldapADServer =LDAP://+ cmdLine.getOptionValue(LDAP);
最后弦乐bindDN = cmdLine.getOptionValue(U);
最后弦乐bindCredential = cmdLine.getOptionValue(P);
最后弦乐baseCtxDN = cmdLine.getOptionValue(D);

最后的哈希表<字符串,对象> ENV =新的Hashtable<字符串,对象>();
env.put(Context.SECURITY_AUTHENTICATION,简单);
env.put(Context.SECURITY_PRINCIPAL,bindDN);
env.put(Context.SECURITY_CREDENTIALS,bindCredential);
env.put(Context.INITIAL_CONTEXT_FACTORYcom.sun.jndi.ldap.LdapCtxFactory);
env.put(Context.PROVIDER_URL,ldapADServer);
env.put(com.sun.jndi.ldap.trace.ber,System.err的);

最后LdapContext的CTX =新InitialLdapContext(ENV,NULL);

最后弦乐searchFilter =(及(objectClass的=用户)(sAMAccountName赋=+帐户名+));

最后的SearchControls的SearchControls =新的SearchControls();
sea​​rchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);

最后StringBuilder的建设者=新的StringBuilder();
最后的NamingEnumeration<信息搜索结果>结果= ctx.search(baseCtxDN,searchFilter,的SearchControls);
而(结果= NULL和放大器;!&安培; results.hasMoreElements()){
    最终的信息搜索结果的结果= results.nextElement();
    builder.append(LdapHelper.getSearchResultDetails(结果,));
}

logger.info(搜索结果:{} {},StringUtils.NEW_LINE,builder.toString());
 

在LdapHelper简单地遍历所有属性,并返回他们在一个很好的格式化字符串。该的objectGUID和的objectSID打印为十六进制格式。

余物在运行测试使用JRE 6以及JRE 7具有相同的结果。我们的广告服务器窗口Server 2008 RC2和我试图同时使用AD端口,389和3268。

我要考虑其他的Java LDAP库,但现在我想看看是否有人碰到这些问题,或有没有人知道这是为什么,以及如何解决它?即有没有办法从公元得到正确的价值观?

感谢。

更新:

我已经使用UnboundID LDAP SDK现在做同样的,这工作正常,返回的完整和正确的objectSID还有的objectGUID。因此,这似乎是在标准的J2SE库中的错误?

code这样做的情况下,任何人有兴趣:

 私有静态无效unboundIdLdapSearch(最后弦乐ldapADServer,最后弦乐bindDN,最后弦乐bindCredential,最后弦乐baseCtxDN,最后弦乐用户名)抛出LDAPException,异常{
    最后LDAPConnection连接=新LDAPConnection(ldapADServer.substring(0,ldapADServer.indexOf(':')),
        的Integer.parseInt(ldapADServer.substring(ldapADServer.indexOf(':')+ 1)),bindDN,bindCredential);
    findAccountByAccountName(连接,baseCtxDN,用户名);
    connection.close()时;
}

私有静态无效findAccountByAccountName(最终LDAPConnection连接,最后弦乐baseCtxDN,最后弦乐帐户名)抛出异常{

    最后弦乐searchFilter =(及(objectClass的=用户)(sAMAccountName赋=+帐户名+));

    logger.info(LDAP搜索过滤器:{},searchFilter);

    最后SearchRequest请求=新的SearchRequest(baseCtxDN,SearchScope.SUB,searchFilter);
    最终com.unboundid.ldap.sdk.SearchResult结果= connection.search(要求);
    最终诠释numOfResults = result.getEntryCount();
    最后StringBuilder的建设者=新的StringBuilder();
    builder.append(与搜索返回).append(numOfResults).append(结果).append(StringUtils.NEW_LINE);
    为(最终SearchResultEntry条目:result.getSearchEntries()){
        builder.append(LdapHelper.getSearchResultDetails(入口,));
    }

    logger.info(搜索结果:{} {},StringUtils.NEW_LINE,builder.toString());
}
 

2日更新

在整个事情发生的原因JNDI LDAP方法并没有为的objectSID和的objectGUID正常工作绊倒,得到它除了我UnboundID解决方案的工作。

首先,我意识到,当我用的getValue返回一个字符串的UnboundID方法,它也返回相同的值的J2SE JNDI的版本做了这是当我想通了,这确实一个字符串转换为UTF -8进口价值。

然后我碰巧遇到另一篇博客中(<一href="http://www.jroller.com/eyallupu/entry/java_jndi_how_to_convert">http://www.jroller.com/eyallupu/entry/java_jndi_how_to_convert)以及本页面:<一href="http://docs.oracle.com/javase/jndi/tutorial/ldap/misc/attrs.html">http://docs.oracle.com/javase/jndi/tutorial/ldap/misc/attrs.html所以所有的需要,为了得到的objectSID和正确的objectGUID是通过添加属性名称的空格分隔列表,以地图为LDAP环境将它们添加到二进制属性的列表:

  env.put(java.naming.ldap.attributes.binary,的objectSID的objectGUID);
 

解决方案

问题终于解决了。见上文第2次更新。

I'm working on a tool to get user details from AD and import them into another system. We were planning on using the objectSid as the unique identifier but I've found that for some reason, the objectSid in the LDAP result does not match what's in Active Directory. Most of the bytes are the same but there are some there are different and sometimes LDAP results have fewer bytes than there are in AD.

objectSid from user in AD:

decimal: [ 1,  5,  0,  0,  0,  0,  0,  5, 21,  0,  0,  0, 35, 106, 222, 96, 236, 251, 239, 68, 32, 255, 234, 203, 122,  4,  0,  0]
hex:     [01, 05, 00, 00, 00, 00, 00, 05, 15, 00, 00, 00, 23,  6A,  DE, 60,  EC,  FB,  EF, 44, 20,  FF,  EA,  CB,  7A, 04, 00, 00]

objectSid for same user via LDAP result:

decimal: [ 1,  5,  0,  0,  0,  0,  0,  5, 21,  0,  0,  0, 35, 106,  63, 96,  63,  63,  63, 68, 32,  63,  63,  63, 122,  4,  0,  0]
hex:     [01, 05, 00, 00, 00, 00, 00, 05, 15, 00, 00, 00, 23,  6A,  3F, 60,  3F,  3F,  3F, 44, 20,  3F,  3F,  3F,  7A, 04, 00, 00]

It almost seems as if any value over 128 comes back as 63/3F in the LDAP result. For another user, the LDAP result is missing 1 byte (the question marks):

hex from AD:   [01 05 00 00 00 00 00 05 15 00 00 00 23 6A DE 60 EC FB EF 44 20 FF EA CB 88 04 00 00]
hex from LDAP: [01 05 00 00 00 00 00 05 15 00 00 00 23 6A 3F 60 3F 3F 3F 44 20 3F 3F 3F ?? 04 00 00]

Here's the main portion of the code I'm using to do these tests.

final String ldapADServer = "ldap://" + cmdLine.getOptionValue("ldap");
final String bindDN = cmdLine.getOptionValue("u");
final String bindCredential = cmdLine.getOptionValue("p");
final String baseCtxDN = cmdLine.getOptionValue("d");

final Hashtable<String, Object> env = new Hashtable<String, Object>();
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, bindDN);
env.put(Context.SECURITY_CREDENTIALS, bindCredential);
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapADServer);
env.put("com.sun.jndi.ldap.trace.ber", System.err);

final LdapContext ctx = new InitialLdapContext(env, null);

final String searchFilter = "(&(objectClass=user) (sAMAccountName=" + accountName + "))";

final SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);

final StringBuilder builder = new StringBuilder();
final NamingEnumeration<SearchResult> results = ctx.search(baseCtxDN, searchFilter, searchControls);
while (results != null && results.hasMoreElements()) {
    final SearchResult result = results.nextElement();
    builder.append(LdapHelper.getSearchResultDetails(result, ""));
}

logger.info("Search results: {}{}", StringUtils.NEW_LINE, builder.toString());

The LdapHelper simply loops through all attributes and returns them in a nicely formatted string. The objectGUID and objectSid are printed in hex format.

I was running the test using JRE 6 as well as JRE 7 with the same result. Our AD server is Window Server 2008 RC2 and I've tried to use both AD ports, 389 and 3268.

I'm going to look into other Java LDAP libraries now but I wanted to see if anyone else had run into these issues or does anyone know why this is and how to get around it? I.e. is there a way to get the proper values from AD?

Thanks.

UPDATE:

I've now done the same using the UnboundID LDAP SDK and this works properly and returns the full and correct objectSid as well as objectGUID. So this seems to be a bug in the standard J2SE library?

Code to do that in case anyone is interested:

private static void unboundIdLdapSearch(final String ldapADServer, final String bindDN, final String bindCredential, final String baseCtxDN, final String userName) throws LDAPException, Exception {
    final LDAPConnection connection = new LDAPConnection(ldapADServer.substring(0, ldapADServer.indexOf(':')),
        Integer.parseInt(ldapADServer.substring(ldapADServer.indexOf(':') + 1)), bindDN, bindCredential);
    findAccountByAccountName(connection, baseCtxDN, userName);
    connection.close();
}

private static void findAccountByAccountName(final LDAPConnection connection, final String baseCtxDN, final String accountName) throws Exception {

    final String searchFilter = "(&(objectClass=user)(sAMAccountName=" + accountName + "))";

    logger.info("LDAP search filter: {}", searchFilter);

    final SearchRequest request = new SearchRequest(baseCtxDN, SearchScope.SUB, searchFilter);
    final com.unboundid.ldap.sdk.SearchResult result = connection.search(request);
    final int numOfResults = result.getEntryCount();
    final StringBuilder builder = new StringBuilder();
    builder.append("Search returned with ").append(numOfResults).append(" results: ").append(StringUtils.NEW_LINE);
    for (final SearchResultEntry entry : result.getSearchEntries()) {
        builder.append(LdapHelper.getSearchResultDetails(entry, ""));
    }

    logger.info("Search results: {}{}", StringUtils.NEW_LINE, builder.toString());
}

2nd UPDATE

Happened to stumble across why the JNDI LDAP method didn't work properly for objectSid and objectGUID and got it working in addition to my UnboundID solution.

First of all, I realized that when I used the UnboundID method of 'getValue' which returns a string, it also returned the same values the J2SE JNDI version did which is when I figured out that this does a String conversion to UTF-8 of the imported value.

I then happened to come across another blog post (http://www.jroller.com/eyallupu/entry/java_jndi_how_to_convert) as well as this page: http://docs.oracle.com/javase/jndi/tutorial/ldap/misc/attrs.html . So all that's needed in order to get the objectSid and objectGUID properly is to add them to the list of binary attributes by adding a space separated list of attribute names to the map for the LDAP context:

env.put("java.naming.ldap.attributes.binary", "objectSid objectGUID");

解决方案

Problem finally solved. See 2nd update above.

这篇关于LDAP查询不返回正确的数据从Active Directory的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆