3

Active Directory (Windows Server 2003) で組織単位を検索しようとしています。これは私のコードです

package com.test;

import java.io.IOException;
import java.util.Properties;

import javax.naming.CompositeName;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.naming.ldap.PagedResultsControl;

public class Main {
    Properties ENV = new Properties();
    private DirContext CTX;
    private static final String BIN_ENV = "java.naming.ldap.attributes.binary";
    private static final String CTX_CLASS = "com.sun.jndi.ldap.LdapCtxFactory";

    String host = "127.0.0.1";
    String port = "389";

    String OU = "OU=b#,DC=domain,DC=local";

    public int getConnection() {
        int result = 0;
        ENV.clear();
        String username = "Administrator@domain.local";
        String password = "admin-123";

        if ((username != null) && (password != null)) {
            ENV.put(Context.SECURITY_AUTHENTICATION, "simple");
            ENV.put(Context.SECURITY_PRINCIPAL, username);
            ENV.put(Context.SECURITY_CREDENTIALS, password);
        }

        ENV.put(Context.INITIAL_CONTEXT_FACTORY, CTX_CLASS);

    ENV.put(Context.PROVIDER_URL, "ldap://" + host + ":" + port);       

        // some attributes must be retrieved in binary format
        ENV.put(BIN_ENV, "userCertificate");
        ENV.put(BIN_ENV, "objectGUID");
        try {
            CTX = new InitialLdapContext(ENV, null);
        } catch (NamingException ex) {
            ENV.clear();
            result = -4;
            if (ex.toString().indexOf("AuthenticationException") > 0) {
                result = -1;
            } else if (ex.toString().indexOf("ConnectException") > 0) {
                result = -2;
            } else if (ex.toString().indexOf("UnknownHostException") > 0) {
                result = -3;
            }
        }
        return result;
    }

    public static void main(String args[]) {
        Main a = new Main();

        String filter = "(&(objectClass=user)(!(objectCategory=computer)))";
        String[] availAttrs = { "objectGUID", "name", "sAMAccountName",
                "distinguishedName", "userCertificate", "userPrincipalName" };

        SearchControls cons = new SearchControls();
        cons.setSearchScope(SearchControls.ONELEVEL_SCOPE);
        cons.setReturningAttributes(availAttrs);

        int result = a.getConnection();

        if (result != 0)
            System.exit(-1);
        try {
            ((LdapContext) a.CTX)
                    .setRequestControls(new Control[] { new PagedResultsControl(
                            1000, Control.CRITICAL) });

            String jndi_dn = new CompositeName().add(a.OU).toString();
            NamingEnumeration<SearchResult> ne = (NamingEnumeration<SearchResult>) a.CTX
                    .search(jndi_dn, filter, cons);

            if ((ne != null) && ne.hasMoreElements()) {

                SearchResult sr = (SearchResult) ne.next();
                String name = sr.getAttributes().get(availAttrs[1]).get(0)
                        .toString();

                System.out.println(name);
            }

        } catch (NamingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

AD の組織単位が「b#」の場合、正常に動作します。しかし、OU が「#b」の場合、javax.naming.InvalidNameException: problem 2006 (BAD_NAME) が発生します。OU 値を "\\#b" として使用することでこの問題を解決できますが、これに二重のバックスプラッシュが必要な理由はまだわかりません。そして、どうすればこれらすべての特別なキャラクターから逃れることができますか? これに対する一般的な解決策はありますか?

4

2 に答える 2

5

この状態は、JNDI のソフトウェアの欠陥が原因であり、JNDI の多くの欠陥の 1 つです。一般に、JNDI は新しいコードには使用しないでください。JNDI はすべての LDAP 標準をサポートしておらず、非推奨の構成を使用しており、多くのソフトウェアの欠陥があります。

代わりにUnboundID LDAP SDKを使用してください。

こちらもご覧ください

于 2012-09-10T11:27:24.653 に答える
2

しかし、これに二重のバックスプラッシュが必要な理由はまだわかりません。

1 つのバックスラッシュは、LDAP クエリ言語のポンド (#) の特別な意味をエスケープするためのものであり、もう 1 つのバックスラッシュは、Java 言語の以前のバックスラッシュをエスケープするためのものです。

そして、どうすればこれらすべての特別なキャラクターから逃れることができますか?

バックスラッシュ文字のみを使用します。Javaプログラムからのクエリでバックスラッシュを使用したい場合は、その1つのバックスラッシュを4つに置き換える必要があります(上記の説明から理由がわかります)。

于 2012-09-10T10:25:33.403 に答える