15

ADからユーザーの詳細を取得して別のシステムにインポートするツールに取り組んでいます。objectSidを一意の識別子として使用することを計画していましたが、何らかの理由で、LDAP結果のobjectSidがActiveDirectoryのオブジェクトSidと一致しないことがわかりました。ほとんどのバイトは同じですが、いくつかは異なり、LDAPの結果のバイト数がADよりも少ない場合があります。

ADのユーザーからのobjectSid:

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]

LDAP結果を介した同じユーザーのobjectSid:

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]

LDAPの結果では、128を超える値が63/3Fとして返されるように見えます。別のユーザーの場合、LDAPの結果に1バイト(疑問符)がありません。

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]

これらのテストを実行するために使用しているコードの主要部分は次のとおりです。

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());

LdapHelperは、すべての属性をループして、適切にフォーマットされた文字列で返します。objectGUIDとobjectSidは16進形式で出力されます。

JRE6とJRE7を使用してテストを実行しましたが、同じ結果になりました。私たちのADサーバーはWindowServer2008 RC2であり、私は389と3268の両方のADポートを使用しようとしました。

今から他のJavaLDAPライブラリを調べますが、他の誰かがこれらの問題に遭遇したかどうか、またはこれがなぜであるか、そしてそれを回避する方法を誰かが知っているかどうかを確認したいと思いました。つまり、ADから適切な値を取得する方法はありますか?

4

1 に答える 1

7

UnboundID LDAP SDKを使用して同じことを実行しました。これは正しく機能し、完全で正しいobjectSidとobjectGUIDを返します。では、これは標準のJ2SEライブラリのバグのようですか?

誰かが興味を持った場合にそれを行うためのコード:

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());
}

さらに、JNDI LDAPメソッドがobjectSidとobjectGUIDに対して正しく機能しない理由に偶然出くわし、UnboundIDソリューションに加えて機能するようになりました。

まず、文字列を返す'getValue'のUnboundIDメソッドを使用すると、J2SE JNDIバージョンと同じ値が返されることに気付きました。これは、文字列をUTF-8に変換することを理解したときです。インポートされた値。

次に、別のブログ投稿( http://www.jroller.com/eyallupu/entry/java_jndi_how_to_convert)とこのページ(http://docs.oracle.com/javase/jndi/tutorial/ldap/ )に偶然出くわしました。 misc/attrs.html。したがって、objectSidとobjectGUIDを適切に取得するために必要なのは、LDAPコンテキストのマップにスペースで区切られた属性名のリストを追加することにより、それらをバイナリ属性のリストに追加することだけです。

env.put("java.naming.ldap.attributes.binary", "objectSid objectGUID");
于 2012-11-05T21:37:02.627 に答える