ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

JAVA JNDI免证书修改AD域密码

2021-03-19 18:01:53  阅读:238  来源: 互联网

标签:JAVA AD JNDI env put import naming javax String


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("weisunqing", "abc123$%")) {
            System.out.println("修改成功");
        }

    }

}

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

标签:JAVA,AD,JNDI,env,put,import,naming,javax,String
来源: https://blog.csdn.net/flying86/article/details/115012438

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有