JAVA JNDI免证书修改AD域密码

Java通过JNDI的方式修改LDAP的密码时需要证书,而使用证书比较繁琐,一大堆复杂的操作导出什么密钥库之类的。且证书1年就失效了还需要企业根证书才行,很多限制!以下的代码为无证书方式修改AD域密码,测试过能够正常修改密码,其关键是配置了DummySSLSocketFactory类,其它相关的说明在代码中已经注明,DummySSLSocketFactory的代码可在下方下载到。

package com.cjzj.ad.util;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AdUtil {

    private static Logger log = LoggerFactory.getLogger(AdUtil.class);

    // AD根目录
    private final String BASEN = "DC=cjzj,DC=com";

    ThreadLocal<DirContext> ctxThreadLocal = new ThreadLocal<DirContext>();

    private Properties initSSLEnv() {

        Properties env = new Properties();
        env.put(Context.AUTHORITATIVE, "true");
        // 修改密码需使用SSL协议
        env.put(Context.SECURITY_PROTOCOL, "ssl");
        env.put(DirContext.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        // 免证书修改AD密码指定的类
        env.put("java.naming.ldap.factory.socket", "com.cjzj.ad.DummySSLSocketFactory");
        // 拥有Domain Admins角色的用户,域管理员
        env.put(Context.SECURITY_PRINCIPAL, "cjzj");
        env.put(Context.SECURITY_CREDENTIALS, "cjzj123$%");
        // 修改时要使用636端口
        env.put(Context.PROVIDER_URL, "ldap://192.168.90.31:636");
        // env.put("com.sun.jndi.ldap.connect.timeout", connectTimeout);
        // Enable connection pooling
        // env.put("com.sun.jndi.ldap.connect.pool", connectPool);
        // env.put("com.sun.jndi.ldap.connect.pool.timeout", connectPoolTimeout);

        return env;
    }

    private boolean modifyPwd(String username, String newPassword) {

        boolean result = false;
        Properties env = null;
        try {
            env = initSSLEnv();

            // 登录
            ctxThreadLocal.set(new InitialDirContext(env));

            log.debug(env.getProperty(Context.SECURITY_PRINCIPAL) + " authenticate is ok!");

            ModificationItem[] mods = new ModificationItem[1];

            String newQuotedPassword = "\"" + newPassword + "\"";

            byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");

            mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
                    new BasicAttribute("unicodePwd", newUnicodePassword));

            // 修改密码
            String userDN = getUserDN(username);
            ctxThreadLocal.get().modifyAttributes(userDN, mods);

            closeContext();
            env.clear();
            env = null;
            log.debug(username + " modify password is success!");
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
            log.warn("username or password is incorrect!", e);
        } finally {
            closeContext();
            if (env != null) {
                try {
                    env.clear();
                    env = null;
                } catch (Exception e) {
                }
            }
        }

        return result;
    }

    /**
     * 获取用户的dn
     *
     * @param username
     * @return
     */
    public String getUserDN(String username) {
        Attributes attrs = getUser(username);
        // distinguishedname这个属性即是用户的dn,可以打印看看
        String userDN = attrs.get("distinguishedname").toString().split(":")[1].trim();
        return userDN;
    }

    /**
     * 查找用户信息
     *
     * @param cn
     * @return
     */
    public Attributes getUser(String cn) {
        Attributes attrs = null;
        SearchControls contro = new SearchControls();
        contro.setSearchScope(SearchControls.SUBTREE_SCOPE);
        try {
            // 有的企业员工的dn不是有cn开头的,而是由uid开头的,这个因企业而异
            // 使用cn,若存在重名用户,则返回的是最后一个员工,存在bug
            // NamingEnumeration en = ctx.search(BASEN, "cn=" + cn, contro);
            // 使用sAMAccountName,避免重名,比如存在四个张伟
            NamingEnumeration<SearchResult> en = ctxThreadLocal.get().search(BASEN, "sAMAccountName=" + cn, contro);
            if (en == null || !en.hasMoreElements()) {
                System.out.println("未找到该用户:" + cn);
                return null;
            }
            while (en.hasMoreElements()) {
                Object obj = en.nextElement();
                if (obj instanceof SearchResult) {
                    SearchResult si = (SearchResult) obj;
                    attrs = si.getAttributes();
                    // attrs是用户的一些相关属性,一些很重要的属性
                    System.out.println(attrs);
                }
            }
        } catch (NamingException e) {
            System.out.println("查找用户异常。。。");
            e.printStackTrace();
        }
        return attrs;
    }

    // 关闭连接
    public void closeContext() {
        try {
            if (ctxThreadLocal.get() != null) {
                ctxThreadLocal.get().close();
                ctxThreadLocal.set(null);
            }
        } catch (NamingException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {

        AdUtil adUtil = new AdUtil();
        if (adUtil.modifyPwd("weiqing", "abc123$%")) {
            System.out.println("修改成功");
        }

    }

}

代码下载:JAVA JNDI免证书修改AD域密码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Java修改AD密码,你可以使用Java的LDAP(轻型目录访问协议)库来实现。以下是一个示例代码: ```java import javax.naming.Context; import javax.naming.NamingException; import javax.naming.directory.Attributes; import javax.naming.directory.BasicAttribute; import javax.naming.directory.BasicAttributes; import javax.naming.directory.ModificationItem; import javax.naming.ldap.InitialLdapContext; import javax.naming.ldap.LdapContext; import java.util.Hashtable; public class ADPasswordChanger { public static void main(String[] args) { String username = "your_username"; String oldPassword = "your_old_password"; String newPassword = "your_new_password"; String ldapURL = "ldap://your_domain_controller:389"; // 替换为你的控制器的URL Hashtable<String, Object> env = new Hashtable<>(); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, username + "@your_domain"); // 替换为你的名 env.put(Context.SECURITY_CREDENTIALS, oldPassword); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, ldapURL); try { LdapContext ctx = new InitialLdapContext(env, null); modifyPassword(ctx, username, newPassword); System.out.println("密码修改成功"); ctx.close(); } catch (NamingException e) { System.out.println("密码修改失败:" + e.getMessage()); } } private static void modifyPassword(LdapContext ctx, String username, String newPassword) throws NamingException { ModificationItem[] mods = new ModificationItem[1]; mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("unicodePwd", newPassword)); ctx.modifyAttributes("CN=" + username, mods); } } ``` 在上面的代码中,你需要替换以下参数: - `your_username`:你的AD用户名 - `your_old_password`:你的AD密码 - `your_new_password`:你想要设置的新密码 - `ldap://your_domain_controller:389`:你的控制器的URL - `your_domain`:你的名 运行代码后,它将尝试使用提供的旧密码连接到AD控制器,然后修改密码为新密码。如果密码修改成功,将会输出"密码修改成功",否则会输出相应的错误信息。请确保你有相应的权限来修改AD密码。 请注意,修改AD密码可能涉及到安全性和权限方面的考虑。在实际使用中,请务必遵守相应的安全策略和最佳实践。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值