使用Java更改AD密码

时间:2009-09-08 21:15:49

标签: java active-directory ldap

我与AD有很好的联系。我可以验证并检查失败的auths的错误消息。

我遇到的问题来自于尝试更改密码。我此时已建立LDAPContext(是的,它是SSL连接)。问题来自于不知道在“username”参数中使用什么值。我已经尝试了所有我能想到的变化,最终得到了三个错误之一:

A)NO_OBJECT - 我假设这意味着它正确地连接到AD但无法找到我正在寻找的东西。

B)DIR_ERROR - 我假设这意味着它可以正确进入AD,但不知道wtf我希望它在那之后做。

C)某种类型的引用错误只有在我不符合DC的条件时才会发生,因此我认为这几乎是给定的。

以下是我正在使用的代码:

public void changePassword(String username, String password) {
    ModificationItem[] mods = new ModificationItem[1];
    String newQuotedPassword = "\"" + password + "\"";
    byte[] newUnicodePassword = newQuotedPassword.getBytes();
    try {
        newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("unicodePwd", newUnicodePassword));
    try {

        ldapContext.modifyAttributes(username, mods);
    } catch (NamingException e) {
        System.out.println("Error changing password for '" + username + "': " + e.getMessage());
        e.printStackTrace();
    }           
}       

4 个答案:

答案 0 :(得分:2)

Spring有LDAP module非常好用。我敢打赌,它会做你需要的。

答案 1 :(得分:1)

答案 2 :(得分:0)

您只能通过修改存储用户的属性来更改用户的密码。相反,您需要使用特殊的LDAP操作SetPassword。我找不到Java引用,只有一个C#和一个Perl

答案 3 :(得分:0)

这是一个有效的例子:

<强> Main.java:

package io.fouad.ldap;

import javax.naming.AuthenticationException;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.*;
import java.io.UnsupportedEncodingException;
import java.util.Hashtable;

public class Main
{
    public static void main(String[] args)
    {
        final String LDAP_SERVERS = "ldap://AD_SERVER:636 ldap://AD_SERVER2:636"; // separated by single spaces
        final String LDAP_CONNECT_TIMEOUT_MS = "10000"; // 10 seconds
        final String LDAP_READ_TIMEOUT_MS = "10000"; // 10 seconds
        final String AUTHENTICATION_DOMAIN = "domain.com";
        final String USERNAME = "username";
        final String OLD_PASSWORD = "123";
        final String NEW_PASSWORD = "456";
        final String TARGET_BASE_DN = "dc=domain,dc=com";

        Hashtable<String, String> ldapEnv = new Hashtable<>();
        ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        ldapEnv.put(Context.PROVIDER_URL, LDAP_SERVERS);
        ldapEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
        ldapEnv.put("java.naming.ldap.version", "3");
        ldapEnv.put(Context.SECURITY_PRINCIPAL, USERNAME + "@" + AUTHENTICATION_DOMAIN);
        ldapEnv.put(Context.SECURITY_CREDENTIALS, OLD_PASSWORD);
        ldapEnv.put(Context.SECURITY_PROTOCOL, "ssl");
        ldapEnv.put("java.naming.ldap.factory.socket", "io.fouad.ldap.MySSLSocketFactory");
        //ldapEnv.put("com.sun.jndi.ldap.connect.timeout", LDAP_CONNECT_TIMEOUT_MS);
        //ldapEnv.put("com.sun.jndi.ldap.read.timeout", LDAP_READ_TIMEOUT_MS);
        DirContext ldapContext = null;

        try
        {
            ldapContext = new InitialDirContext(ldapEnv);
        }
        catch(AuthenticationException e)
        {
            System.out.println("Wrong username/password!");
            e.printStackTrace();
        }
        catch(NamingException e)
        {
            e.printStackTrace();
        }

        if(ldapContext == null) return;


        SearchControls searchControls = new SearchControls();
        searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
        NamingEnumeration objects = null;
        try
        {
            objects = ldapContext.search(TARGET_BASE_DN, String.format("(&(objectClass=user)(sAMAccountName=%s))", USERNAME), searchControls);
        }
        catch(NamingException e)
        {
            e.printStackTrace();
        }

        if(objects == null) return;

        try
        {
            if(objects.hasMore())
            {
                SearchResult entry = (SearchResult) objects.next();
                ModificationItem[] mods = new ModificationItem[2];
                mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, new BasicAttribute("unicodePwd", getPasswordByteArray(OLD_PASSWORD)));
                mods[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE, new BasicAttribute("unicodePwd", getPasswordByteArray(NEW_PASSWORD)));
                ldapContext.modifyAttributes(entry.getName() + "," + TARGET_BASE_DN, mods);

                System.out.println("Successfully changed the password!");
            }
            else
            {
                System.out.println("User (" + USERNAME + ") was not found!");
            }
        }
        catch(NamingException e)
        {
            e.printStackTrace();
        }

        System.out.println("DONE!");

    }

    private static byte[] getPasswordByteArray(String password)
    {
        String quotedPassword = "\"" + password + "\"";
        try
        {
            return quotedPassword.getBytes("UTF-16LE");
        }
        catch(UnsupportedEncodingException e)
        {
            e.printStackTrace();
            return null;
        }
    }
}

MySSLSocketFactory.java:(使用它需要您自担风险)

package io.fouad.ldap;

import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

public class MySSLSocketFactory extends SSLSocketFactory
{
    private SSLSocketFactory socketFactory;

    public MySSLSocketFactory()
    {
        try
        {
            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(null, new TrustManager[] {new X509TrustManager()
            {
                @Override
                public void checkClientTrusted(X509Certificate[] x509Certificates, String s){}

                @Override
                public void checkServerTrusted(X509Certificate[] x509Certificates, String s){}

                @Override
                public X509Certificate[] getAcceptedIssuers()
                {
                    return new X509Certificate[0];
                }
            }}, new SecureRandom());

            socketFactory = ctx.getSocketFactory();
        }
        catch(Exception ex)
        {
            ex.printStackTrace(System.err);
        }
    }

    public static SocketFactory getDefault()
    {
        return new MySSLSocketFactory();
    }

    @Override
    public String[] getDefaultCipherSuites()
    {
        return socketFactory.getDefaultCipherSuites();
    }

    @Override
    public String[] getSupportedCipherSuites()
    {
        return socketFactory.getSupportedCipherSuites();
    }

    @Override
    public Socket createSocket(Socket socket, String string, int i, boolean bln) throws IOException
    {
        return socketFactory.createSocket(socket, string, i, bln);
    }

    @Override
    public Socket createSocket(String string, int i) throws IOException
    {
        return socketFactory.createSocket(string, i);
    }

    @Override
    public Socket createSocket(String string, int i, InetAddress ia, int i1) throws IOException
    {
        return socketFactory.createSocket(string, i, ia, i1);
    }

    @Override
    public Socket createSocket(InetAddress ia, int i) throws IOException
    {
        return socketFactory.createSocket(ia, i);
    }

    @Override
    public Socket createSocket(InetAddress ia, int i, InetAddress ia1, int i1) throws IOException
    {
        return socketFactory.createSocket(ia, i, ia1, i1);
    }
}