JAVA使用Ldap操作AD域

项目上遇到的需要在集成 操作域用户的信息的功能,第一次接触ad域,因为不了解而且网上其他介绍不明确,比较费时,这里记录下。

说明:

(1). 特别注意:Java操作查询域用户信息获取到的数据和域管理员在电脑上操作查询的数据可能会存在差异(同一个意思的表示字段,两者可能不同)。

(2). 连接ad域有两个地址: ldap://XXXXX.com:389 和 ldap://XXXXX.com:636(SSL)。

(3). 端口389用于一般的连接,例如登录,查询等非密码操作,端口636安全性较高,用户密码相关操作,例如修改密码等。

(4).  域控可能有多台服务器,之间数据同步不及时,可能会导致已经修改的数据被覆盖掉,这个要么域控缩短同步的时间差,要么同时修改每一台服务器的数据。

1. 389登录

// 只要不抛出异常就是验证通过public LdapContext adLogin(JSONObject json) {
        String username = json.getString("username");
        String password = json.getString("password");
        String server = "ldap://XXXXXXX.com:389";
        try {
            Hashtable<String, String> env = new Hashtable<String, String>();
            //用户名称,cn,ou,dc 分别:用户,组,域
            env.put(Context.SECURITY_PRINCIPAL, username);
            //用户密码 cn 的密码
            env.put(Context.SECURITY_CREDENTIALS, password);
            //url 格式:协议://ip:端口/组,域   ,直接连接到域或者组上面
            env.put(Context.PROVIDER_URL, server);
            //LDAP 工厂
            env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
            //验证的类型     "none", "simple", "strong"
            env.put(Context.SECURITY_AUTHENTICATION, "simple");
            LdapContext ldapContext = new InitialLdapContext(env, null);
            log.info("ldapContext:" + ldapContext);
            log.info("用户" + username + "登录验证成功");
            return ldapContext;

        } catch (NamingException e) {
            log.info("用户" + username + "登录验证失败");
            log.info("错误信息:"+e.getExplanation());
            return null;
        }
    }

2. 636登录验证(需要导入证书)

//证书提前倒入的Java库中
// 参考:https://www.cnblogs.com/moonson/p/4454159.html

LdapContext adLoginSSL(JSONObject json) {
String username = json.getString("username");
String password = json.getString("password");
Hashtable env = new Hashtable();

String javaHome = System.getProperty("java.home");
         String keystore = javaHome+"/lib/security/cacerts";
         log.info("java.home,{}",keystore);
    // 加载导入jdk的域证书
         System.setProperty("javax.net.ssl.trustStore", keystore);
         System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
         String LDAP_URL = "ldap://XXXXXX.com:636"; // LDAP访问地址

         env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
         env.put(Context.SECURITY_PROTOCOL, "ssl");//链接认证服务器
         env.put(Context.PROVIDER_URL, LDAP_URL);
         env.put(Context.SECURITY_AUTHENTICATION, "simple");
         env.put(Context.SECURITY_PRINCIPAL, username);
         env.put(Context.SECURITY_CREDENTIALS, password);
         try {
             LdapContext ldapContext = new InitialLdapContext(env, null);
             log.info("认证成功");// 这里可以改成异常抛出。
             return ldapContext;
         } catch (javax.naming.AuthenticationException e) {
             log.info("认证失败:{}",e.getMessage());
         } catch (Exception e) {
             log.info("认证出错:{}",e.getMessage());
         }
        return null;
    }

3. 查询域用户信息

public List getUserKey(JSONObject json){

        JSONObject admin = new JSONObject();
        admin.put("username","Aaaaa");
        admin.put("password", "bbbbbbbb");
        String name = json.getString("name");
        log.info("需要查询的ad信息:{}",name);
        List<JSONObject> resultList = new JSONArray();
        LdapContext ldapContext = adLogin(admin); //连接到域控
        if (ldapContext!=null){

            String company = "";
            String result = "";
            try {
                // 域节点
                String searchBase = "DC=XXXXXXX,DC=com";
                // LDAP搜索过滤器类
                //cn=*name*模糊查询          //cn=name 精确查询
          // String searchFilter = "(objectClass="+type+")";
               String searchFilter = "(sAMAccountName="+name+")";    //查询域帐号

                // 创建搜索控制器
                SearchControls searchCtls = new SearchControls();
                String  returnedAtts[]={"description","sAMAccountName","userAccountControl"};                        searchCtls.setReturningAttributes(returnedAtts); //设置指定返回的字段,不设置则返回全部
                //  设置搜索范围 深度
                searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
                // 根据设置的域节点、过滤器类和搜索控制器搜索LDAP得到结果
                NamingEnumeration answer = ldapContext.search(searchBase, searchFilter,searchCtls);
                // 初始化搜索结果数为0
                int totalResults = 0;
                int rows = 0;
                while (answer.hasMoreElements()) {// 遍历结果集
                    SearchResult sr = (SearchResult) answer.next();// 得到符合搜索条件的DN
                    ++rows;
                    String dn = sr.getName();
                    log.info(dn);
                    Attributes Attrs = sr.getAttributes();// 得到符合条件的属性集
                    if (Attrs != null) {
                        try {
                            for (NamingEnumeration ne = Attrs.getAll(); ne.hasMore();) {
                                Attribute Attr = (Attribute) ne.next();// 得到下一个属性
                                // 读取属性值
                                for (NamingEnumeration e = Attr.getAll(); e.hasMore(); totalResults++) {
                                    company = e.next().toString();
                                    JSONObject tempJson = new JSONObject();

                                    tempJson.put(Attr.getID(), company.toString());
                                    resultList.add(tempJson);
                                }
                            }
                        } catch (NamingException e) {
                            log.info("Throw Exception : " + e.getMessage());
                        }
                    }
                }
                               log.info("总共用户数:" + rows);
            } catch (NamingException e) {
                log.info("Throw Exception : " + e.getMessage());
            }finally {
                try{
                    ldapContext.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
        return resultList;
    }

4. 重置用户密码

// 管理员重置用户密码,后强制用户首次登录修改密码
public Map<String, String> updateAdPwd(JSONObject json) {
        String dn = json.getString("dn");//要修改的帐号(这个dn是查询的用户信息里的dn的值,而不是域账号)
        String password = json.getString("password");//新密码

        JSONObject admin = new JSONObject();
        admin.put("username","aaaaaaa");
        admin.put("password", "bbbbbbb");
        Map<String,String> map = new HashMap<String,String>();
        LdapContext ldapContext = adLoginSSL(admin); //连接636端口域
        ModificationItem[] mods = new ModificationItem[2];
        if (ldapContext!=null){
            try {
                String newQuotedPassword = "\"" + password + "\"";
                byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");
// unicodePwd:修改的字段,newUnicodePassword:修改的值
                mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
                        new BasicAttribute("unicodePwd", newUnicodePassword));
mods[1] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
                        new BasicAttribute("pwdLastSet", "0"));  // 首次登录必须修改密码

                // 修改密码
                ldapContext.modifyAttributes(dn, mods);
                map.put("result", "S");
                map.put("message","成功");
            }catch (Exception e){
                map.put("result","E");
                map.put("message", "无法重置密码");
            }finally {
                try{
                    ldapContext.close();
                }catch (Exception e){
                    e.printStackTrace();
                }

            }

        }else {
            log.info("");
            map.put("result","E");
            map.put("message", "验证失败");
        }

        return map;
    }

5. 域账号解锁

// 表示锁定的字段需要测试,不一定这个lockoutTimepublic Map<String, String> deblocking(JSONObject json) {
    JSONObject admin = new JSONObject();
    String dn = json.getString("dn"); //被解锁的帐号(这个dn指的是查询用户信息里的dn的值,不是域账号)
    admin.put("username","aaaaaa");
    admin.put("password","bbbbbb");
    Map<String,String> map = new HashMap<String,String>();
    LdapContext ldapContext = adLogin(admin);
    ModificationItem[] mods = new ModificationItem[1];
    if (ldapContext!=null){
        try {
      // "0" 表示未锁定,不为0表示锁定
            mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
                    new BasicAttribute("lockoutTime","0"));
            // 解锁域帐号
            ldapContext.modifyAttributes(dn, mods);
            map.put("result", "S");
            map.put("message","成功");
        }catch (Exception e){
            map.put("result","E");
            map.put("message", "解锁失败");
        }finally {
            try{
                ldapContext.close();
            }catch (Exception e){
                e.printStackTrace();
            }

        }

    }else {
        map.put("result","E");
        map.put("message", "验证失败");
    }
    return map;
}

原文地址:https://www.cnblogs.com/sunjiguang/p/9257585.html

时间: 2024-10-23 15:38:19

JAVA使用Ldap操作AD域的相关文章

Java使用LdAP获取AD域用户

随着我们的习大大上台后,国家在网络信息安全方面就有了很明显的改变!所以现在好多做网络信息安全产品的公司和需要网络信息安全的公司都会提到用AD域服务器来验证,这里就简单的研究了一下! 先简单的讲讲AD域和LdAP目录访问协议:AD(active directory)活动目录,动态的建立整个域模式网络中的对象的数据库或索引,协议为LDAP,安装了AD的服务器称为DC域控制器,存储整个域的对象的信息并周期性更新!其中的对象分为三大类--资源(如印表机).服务(如电子邮件).和人物(即帐户或用户,以及组

JAVA 通过LDAP获取AD域用户及组织信息

因为工作需求近期做过一个从客户AD域获取数据实现单点登录的功能,在此整理分享. 前提:用户可能有很多系统的情况下,为了方便账号的统一管理使用AD域验证登录,所以不需要我们的系统登录,就需要获取用户的AD域组织和用户信息,实现域认证和单点登录. LDAP: LDAP是轻量目录访问协议 AD域:微软基于域模式的集中化管理 1.常规的AD域登陆验证 LdapContext dc = null;             Hashtable<String, String> env = new Hasht

利用LDAP操作AD域

LDAP操作代码样例  初始化LDAP 目录服务上下文 该例子中,我们使用uid=linly,ou=People,dc=jsoso,dc=net这个账号,链接位于本机8389端口的LDAP服务器(ldap://localhost:8389),认证方式采用simple类型,即用户名/密码方式. private static void initialContext() throws NamingException{    if(singleton == null){     singleton =

关于Ldap对AD域账户的增删改查

今天心情很不爽,那啥也不懂的老板,又来直接修改了我的需求,还很自信的对我们研发人员说:"他这产品经理已经做得很好了!",在这里我回复一句,以我这么多年的经验,做得跟一条狗似的,还自我感觉良好!!!好啦,不扯别的啦,来讲讲Ldap对AD域账户的操作吧!至于Ldap和ad今天就不做详细解释了,有兴趣的朋友可以看看上一篇博文,里面有详细的介绍!直接上代码: /** * @Description: * * @Title: LdapByUser.java * @Package com.joyce

java以及C#获取AD域上用户信息

JAVA /** *  JAVA 读取AD用户信息 *  aa00a00 */package com.wanda.sso.client.servlet; import java.util.Hashtable; import javax.naming.Context;import javax.naming.NamingEnumeration;import javax.naming.NamingException;import javax.naming.directory.Attribute;imp

.net操作AD域

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Configuration;using System.DirectoryServices;namespace OperateADLibrary{    public class OperateAD    {        /// <summary>        /// 域名        /// <

Ubuntu通过LDAP集成AD域账号登录(libnss-ldap方式)

Ubuntu通过LDAP集成AD域账号登录(libnss-ldap方式): # apt-get install libnss-ldap   (中间直接回车,忽略) # vi /etc/nsswitch.conf passwd: files ldap group:  files ldap shadow: files ldap :wq # vi /etc/ldap.conf base dc=ming,dc=com uri ldap://10.0.0.2 binddn cn=ldapadmin,cn=

Java利用jcifs集成AD域用户认证

最近一段时间发现AD这东西老火了,尤其是涉及到安全这一方面的,所以AD域用户认证成了现在网络安全方面的产品必备!这里就简单的分享一下,Java通过jcifs集成AD域用户实现认证,以实现网络安全! 我们通过一个demo来看看jcifs实现SSO,SSO英文全称Single Sign On,单点登录.SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.它包括可以将这次主要的登录映射到其他应用中用于同一 个用户的登录的机制.它是目前比较流行的企业业务整合的解决方案之一. 第

CentOS 6通过ldap集成AD域账号(nslcd方式)

CentOS 6通过ldap集成AD域账号(nslcd方式): CentOS 6默认有安装nss-pam-ldapd软件(rpm -qa nss-pam-ldapd,rpm -ql nss-pam-ldapd) vi /etc/nsswitch.conf passwd: files ldapgroup: files ldapshadow: files ldap:wq vi /etc/nslcd.conf binddn cn=aa,cn=users,dc=ming,dc=com (aa为普通AD账