как получить атрибут «unicodePwd» в Active Directory с помощью программирования на Java

#java #active-directory #utf-16le

#java #active-directory #utf-16le

Вопрос:

Прежде всего, я прошу прощения за мой плохой английский. Я бразилец, поэтому, если в тексте есть какие-либо ошибки, пожалуйста, просто подумайте.

Я прочитал здесь много статей о получении атрибута «unicodePwd» в Active Directory, но ни одна из них мне не помогла.

Ну, зачем мне нужна эта информация? Я объясню:

Здесь у меня есть несколько Java-подпрограмм, которые объединяют пользовательскую информацию из разных систем друг в друга. Эти процедуры получают необходимую информацию в основной базе данных Oracle и устанавливают информацию в других базах данных (в основном Oracle и MySQL).

Например: у нас есть частная облачная система, которая работает в ОС CentOS Linux и имеет собственную базу данных MySQL. Чтобы объединить информацию о пользователях, включая пароли пользователей, мы получаем информацию из основной базы данных Oracle и настраиваем базу данных MySQL этой системы, чтобы объединить данные пользователя и информацию для входа.

Все процедуры, которые у меня здесь есть, работают, и проблем нет, но теперь у нас есть новая задача.

Нам нужно выполнить ту же унификацию с нашими пользователями Active Directory, получив необходимую информацию в этой основной базе данных Oracle, а затем установив всю информацию для пользователей Active Directory, включая пароли пользователей.

Я уже успешно обновил пароль у пользователей Active Directory, но я не хочу, чтобы пароль обновлялся каждый раз, когда выполняется эта процедура Java, но только при изменении пароля в основной базе данных Oracle.

Пример: Когда один из пользователей меняет пароль в основной базе данных Oracle, подпрограмма Java получает эту информацию о пользователе, чтобы затем установить для того же пользователя в Active Directory. Чтобы сделать это правильно, подпрограмма получает ту же информацию в Active Directory, затем сравнивает оба пароля (пароль Oracle и пароль Active Directory) и, наконец, если пароль отличается, подпрограмма обновит его, но если пароль не отличается, подпрограмма ничего не сделает.

Вот почему мне нужно получить атрибут «unicodePwd» в Active Directory.

Вот часть моего кода:

 import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.*;
import org.apache.commons.mail.EmailException;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;

public class ldapQuery {        

    String distinguishedName = "";
    String department = "";
    String physicalDeliveryOfficeName = "";
    String telephoneNumber = "";
    String mobile = "";
    String title = "";
    String sAMAccountName = "";
    String unicodePwd = "";

    public ldapQuery(String mail) {

        try {
            final Hashtable<String, String> env = new Hashtable<String, String>();
            final String adminName = "CN=MY DOMAIN ADMIN,CN=MY DOMAIN ADMIN FOLDER LOCALIZATION,DC=MY DOMAIN,DC=MY DOMAIN,DC=MY DOMAIN";
            final String adminPasswd = "MY DOMAIN ADMIN PASSWORD";
            final String ldapUrl = "ldaps://MY ACTIVE DIRECTORY SERVER:636";
            final String factory = "com.sun.jndi.ldap.LdapCtxFactory";
            final String authType = "simple";
            final String protocol = "ssl";
            env.put(Context.INITIAL_CONTEXT_FACTORY, factory);
            env.put(Context.SECURITY_AUTHENTICATION, authType);
            env.put(Context.SECURITY_PRINCIPAL, adminName);
            env.put(Context.SECURITY_CREDENTIALS, adminPasswd); 
            env.put(Context.SECURITY_PROTOCOL, protocol);
            env.put(Context.PROVIDER_URL, ldapUrl);     
            DirContext ctx = new InitialLdapContext (env,null);

            SearchControls searchCtls = new SearchControls();
            String returnedAtts[] = {"sAMAccountName", "distinguishedName","department", "physicalDeliveryOfficeName", "telephoneNumber", "mobile", "title", "unicodePwd"};
            searchCtls.setReturningAttributes(returnedAtts);
            searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
            String searchFilter = "(amp;(objectClass=user)(mail="   mail  "))";
            String searchBase = "DC=MY DOMAIN,DC=MY DOMAIN,DC=MY DOMAIN";
            int totalResults = 0;
            NamingEnumeration<SearchResult> answer =ctx.search(searchBase, searchFilter, searchCtls);

            while (answer.hasMoreElements()) {
                SearchResult sr = (SearchResult)answer.next();
                totalResults  ; 
                Attributes attrs = sr.getAttributes();

                if (attrs != null) {

                    distinguishedName = (String) attrs.get("distinguishedName").get();
                    department = (String) attrs.get("department").get();
                    physicalDeliveryOfficeName = (String) attrs.get("physicalDeliveryOfficeName").get();
                    telephoneNumber = (String) attrs.get("telephoneNumber").get();
                    mobile = (String) attrs.get("mobile").get();
                    title = (String) attrs.get("title").get();
                    sAMAccountName = (String) attrs.get("sAMAccountName").get();

                    Attribute passwd = attrs.get("unicodePwd");
                    unicodePwd = unicodePwd   passwd;

                    if (department == null) {
                        department = "";
                    }

                    if (physicalDeliveryOfficeName == null) {
                        physicalDeliveryOfficeName = "";
                    }

                    if (telephoneNumber == null) {
                        telephoneNumber = "";
                    }

                    if (mobile == null) {
                        mobile = "";
                    }

                    if (title == null) {
                        title = "";
                    }
                }
            }
        }

        catch (NamingException e){
            System.err.println("FAIL MESSAGE: "   e);
        }
    }

    public String ldapSearchResultDistinguishedName() {
        return distinguishedName;
    }

    public String ldapSearchResultDepartment() {
        return department;
    }

    public String ldapSearchResultPhysicalDeliveryOfficeName() {
        return physicalDeliveryOfficeName;
    }

    public String ldapSearchResultTelephoneNumber() {
        return telephoneNumber;
    }

    public String ldapSearchResultMobile() {
        return mobile;
    }

    public String ldapSearchResultTitle() {
        return title;
    }

    public String ldapSearchResultUnicodePwd() {
        return unicodePwd;
    }

    public String ldapSearchResultSAMAccountName() {
        return sAMAccountName;
    }
}
  

После запуска кода все переменные возвращают правильную информацию, кроме переменной «unicodePwd», которая возвращает «null», даже если у пользователя есть пароль.

Я знаю о байте UTF-16LE и о том, что поле «unicodePwd» в Active Directory зашифровано, но, как я объяснял ранее, мне нужна эта информация, расшифрованная в строковой переменной.

Есть идеи?

Спасибо!

Ответ №1:

Я знаю, что это старый вопрос, но я наткнулся на него, поскольку я также искал ответ на тот же вопрос. Я нашел ответ и подумал, что это может помочь кому-нибудь еще, кто попадает сюда.

Согласно документации Microsoft, может показаться, что атрибут unicodePwd НИКОГДА не возвращается при поиске LDAP.

В моем случае мне нужно проверить правильность полученных учетных данных. Итак, мой план состоит в том, чтобы использовать полученное имя пользователя / пароль и создать пользовательский LdapContextFactory «на лету» с этими учетными данными. Если я смогу успешно связаться с сервером, выполнив LdapContextFactory.get и получить обратно LdapContext, тогда я могу быть уверен, что предоставленный пароль был правильным. Если вы не получите его обратно, вы знаете, что это неправильно, и можете взять его оттуда.