AD域用户及组织架构同步、AD域用户登录验证、AD域nginx端口转发

1.对AD域操作的一个工具类


import com.ruoyi.system.api.domain.SysUser;

import org.apache.commons.compress.utils.Lists;

import javax.naming.Context;

import javax.naming.NamingEnumeration;

import javax.naming.NamingException;

import javax.naming.directory.*;

import javax.naming.ldap.InitialLdapContext;

import java.util.List;

import java.util.Properties;

/**

* @Description:对AD域用户的增删改查操作

* @author moonxy

* @date 2018-05-15

*/

public class ADUserUtils{

    DirContextdc =null;

    public static final Stringroot ="OU=xxxxx,DC=xxxxx,DC=COM"; // LDAP的根节点的DC

    /**

    * @Description:程序入口

    * @author moonxy

    * @date 2018-05-15

*/

//    public static void main(String[] args) {

//        ADUserUtils utils = new ADUserUtils();

//

////        utils.add("JimGreen");

//

////        SearchResult sr = utils.searchByUserName(utils.root, "JimGreen");

////        System.out.println(sr.getName());

////

////        utils.modifyInformation(sr.getName(), "M1380005");

//

//          utils.searchInformation(utils.root);

//

////        utils.renameEntry("CN=JimGreen,OU=Java开发组,OU=软件研发部,DC=moonxy,DC=com", "CN=JimGreen,OU=Web前端组,OU=软件研发部,DC=moonxy,DC=com");

//

////        utils.delete("CN=JimGreen,OU=Web前端组,OU=软件研发部,DC=moonxy,DC=com");

//

//        utils.close();

//    }

    /**

    * 初始化

    */

    public ADUserUtils() {

        super();

        init();

    }

    /**

    * @Description:初始化AD域服务连接

    * @date 2018-05-15

*/

    public void init() {

        Properties env =new Properties();

        String adminName ="xxxx";//username@domain

        String adminPassword ="xxxx";//password

        String ldapURL ="ldap://ip:port";//ip:port

        env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");

        env.put(Context.SECURITY_AUTHENTICATION, "simple");//LDAP访问安全级别:"none","simple","strong"

        env.put(Context.SECURITY_PRINCIPAL, adminName);

        env.put(Context.SECURITY_CREDENTIALS, adminPassword);

        env.put(Context.PROVIDER_URL, ldapURL);

        env.put("com.sun.jndi.ldap.connect.timeout", "3000");

        try {

            dc =new InitialLdapContext(env, null);

            System.out.println("AD域服务连接认证成功");

        } catch (Exception e) {

            System.out.println("AD域服务连接认证失败");

            e.printStackTrace();

        }

    }

    /**

    * @Description:关闭AD域服务连接

    * @author moonxy

    * @date 2018-05-15

*/

    public void close() {

        if (dc !=null) {

            try {

                dc.close();

            } catch (NamingException e) {

                System.out.println("NamingException in close():" + e);

            }

        }

    }

    /**

    * @Description:新增AD域用户

    * @author moonxy

    * @date 2018-05-15

*/

    public void add(String newUserName) {

        try {

            Attributes attrs =new BasicAttributes(true);

            attrs.put("objectClass", "user");

            attrs.put("samAccountName", newUserName);

            attrs.put("displayName", newUserName);

            attrs.put("userPrincipalName", newUserName +"@moonxy.com");

            dc.createSubcontext("CN=" + newUserName +"," +root, attrs);

            System.out.println("新增AD域用户成功:" + newUserName);

        } catch (Exception e) {

            e.printStackTrace();

            System.out.println("新增AD域用户失败:" + newUserName);

        }

    }

    /**

    * @Description:删除AD域用户

    * @author moonxy

    * @date 2018-05-15

*/

    public void delete(String dn) {

        try {

            dc.destroySubcontext(dn);

            System.out.println("删除AD域用户成功:" + dn);

        } catch (Exception e) {

            System.out.println("删除AD域用户失败:" + dn);

            e.printStackTrace();

        }

    }

    /**

    * @Description:重命名AD域用户

    * @author moonxy

    * @date 2018-05-15

*/

    public boolean renameEntry(String oldDN, String newDN) {

        try {

            dc.rename(oldDN, newDN);

            System.out.println("重命名AD域用户成功");

return true;

        } catch (NamingException ne) {

            System.out.println("重命名AD域用户失败");

            ne.printStackTrace();

return false;

        }

    }

    /**

    * @Description:修改AD域用户属性

    * @author moonxy

    * @date 2018-05-15

*/

    public boolean modifyInformation(String dn, String fieldValue) {

        try {

            ModificationItem[] mods =new ModificationItem[1];

            // 修改属性

            Attribute attr0 =new BasicAttribute("homePhone",fieldValue);

            //mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, attr0);//新增属性

            //mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE,attr0);//删除属性

            mods[0] =new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr0);//覆盖属性

            dc.modifyAttributes(dn +"," +root, mods);

            System.out.println("修改AD域用户属性成功");

return true;

        } catch (Exception e) {

            System.err.println("修改AD域用户属性失败");

            e.printStackTrace();

return false;

        }

    }

    /**

    * @Description:搜索指定节点下的所有AD域用户

    * @author moonxy

    * @date 2018-05-15

*/

    public List<SysUser> searchInformation(String searchBase,String searchFilter,String[] returnedAtts) {

        List<SysUser> userList = Lists.newArrayList();

        try {

            SearchControls searchCtls =new SearchControls();

            searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);

            searchCtls.setReturningAttributes(returnedAtts);

            NamingEnumeration<SearchResult> answer =dc.search(searchBase, searchFilter, searchCtls);

            while (answer.hasMoreElements()) {

                SearchResult sr =(SearchResult) answer.next();

                setUserModelList(sr,userList);

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

        return userList;

    }

    private void setUserModelList(SearchResult sr,List<SysUser> userList){

        SysUser user =new SysUser();

        NamingEnumeration<?extends Attribute> attrs  = sr.getAttributes().getAll();

        while (attrs.hasMoreElements()){

            Attribute attribute = attrs.nextElement();

            String attr_str = attribute.toString();

            int spilt_num = attr_str.indexOf(":");

            String attr_param = attr_str.substring(0, spilt_num);

            String attr_value = attr_str.substring(spilt_num +2);

            if (attr_param.equals("name")) {

                user.setUserName(attr_value);

            } else if (attr_param.equals("displayName")) {

                user.setNickName(attr_value);

            } else if (attr_param.equals("mail")) {

                user.setEmail(attr_value);

            } else if (attr_param.equals("mobile")) {

                user.setPhonenumber(attr_value);

            } else if (attr_param.equals("telephonenumber")) {

                user.setTelephoneNumber(attr_value);

            } else if (attr_param.equals("initials")) {

                user.setSex("男".equals(attr_value)?"0":"1");

            }

        }

        String name = sr.getName();

        String[] split = name.split(",");

        if (split.length>1) {

            String[] split1 = split[1].split("=");

            if (split1.length>1) {

                user.setAvatar(split1[1]);

            }

        }

        if (!userList.contains(user)) {

            userList.add(user);

        }

    }

    /**

    * @Description:指定搜索节点搜索指定域用户

    * @author moonxy

    * @date 2018-05-15

*/

    public SearchResultsearchByUserName(String searchBase, String userName) {

        SearchControls searchCtls =new SearchControls();

        searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);

        String searchFilter ="sAMAccountName=" + userName;

        String returnedAtts[] ={ "memberOf" }; //定制返回属性

        searchCtls.setReturningAttributes(returnedAtts); //设置返回属性集

        try {

            NamingEnumeration<SearchResult> answer =dc.search(searchBase, searchFilter, searchCtls);

            return answer.next();

        } catch (Exception e) {

            System.err.println("指定搜索节点搜索指定域用户失败");

            e.printStackTrace();

        }

        return null;

    }

}




2.AD域用户登录验证

原理:根据用户提交的用户名和密码,去连接AD域认证。通过用户名在AD域指定节点下查找出该用户的nameInNamespace,这个属性是用户最精确的base。通过这个base跟密码去AD验证。



@Component

public class ADUserLoginService{

    public  BooleanadUserValidate(String username,String password) {

        ADUserUtils utils =new ADUserUtils();

        SearchResult sr = utils.searchByUserName(utils.root, username);

        utils.close();

        String nameInNamespace ="";

        if (sr!=null) {

            nameInNamespace = sr.getNameInNamespace();

        }

        Boolean flag =true;

        DirContext ctx=null;

        Properties env =new Properties();

        String ldapURL ="ldap://ip:port";//ip:port

        env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");

        env.put(Context.SECURITY_AUTHENTICATION, "simple");//LDAP访问安全级别:"none","simple","strong"

        env.put(Context.SECURITY_PRINCIPAL, nameInNamespace);

        env.put(Context.SECURITY_CREDENTIALS, password);

        env.put(Context.PROVIDER_URL, ldapURL);

        env.put("com.sun.jndi.ldap.connect.timeout", "3000");

        try {

            ctx =new InitialLdapContext(env,null);// 初始化上下文

            System.out.println("身份验证成功!");

        } catch (AuthenticationException e) {

            System.out.println("身份验证失败!");

            flag =false;

            e.printStackTrace();

        } catch (javax.naming.CommunicationException e) {

            System.out.println("AD域连接失败!");

            flag =false;

            e.printStackTrace();

        } catch (Exception e) {

            System.out.println("身份验证未知异常!");

            flag =false;

            e.printStackTrace();

        } finally{

            if(null!=ctx){

                try {

                    ctx.close();

                    ctx=null;

                } catch (Exception e) {

                    e.printStackTrace();

                }

            }

        }

        return flag;

    }

}



3、AD域nginx端口转发代理

由于生产环境不能直接访问ldap://ip:port,在可以访问AD域的服务器上的nginx上配置

在nginx.conf文件下,添加如下配置:

events {

worker_connections  1024;

}

# ================================================================= #

# --------------------------- ldap端口转发 ------------------------ #

# ================================================================= #

# 说明: 源码configure时需要执行如下命令:

# ./configure --prefix=/usr/local/nginx   --with-http_stub_status_module --with-stream

# make & make install

# 方法一: use

stream {

server {

listen 1389;

proxy_pass 10.196.71.162:1389;

proxy_timeout 5s;

proxy_connect_timeout 5s;

proxy_busy_buffers_size 64k;

}

}

# 方法二(负载均衡方案)

stream {

upstream ldap {

hash $remote_addr consistent;

server 10.6.60.122:389;

}

server {

listen 10000;

proxy_connect_timeout 5s;

proxy_timeout 5s;

proxy_pass ldap;

}

}

http {

...

}

生产服务器申请开通访问nginx所在机器的ldap转发端口,可以通过ldap://nginx:转发端口,访问AD域



最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容