LdapHelper.java
package com.mycim.webapp.utils;
import com.mycim.framework.logging.Logger;
import com.mycim.framework.logging.LoggerFactory;
import com.mycim.framework.utils.lang.StringUtils;
import com.mycim.framework.utils.lang.collections.MapUtils;
import com.mycim.framework.utils.msg.JsonUtils;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.*;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import java.util.*;
public class LdapHelper {
private static final Logger logger = LoggerFactory.getLogger(LdapHelper.class);
@SuppressWarnings(value = "unchecked")
public static LdapContext getCtx(Map<String, Object> ldapInfo) throws NamingException {
//String authenticationType = MapUtils.getString(ldapInfo, "authenticationType");
String principalSuffix = MapUtils.getString(ldapInfo, "principalSuffix");
String providerUrl = MapUtils.getString(ldapInfo, "providerUrl");
String baseDn = MapUtils.getString(ldapInfo, "baseDn");
String factoryInitial = MapUtils.getString(ldapInfo, "factoryInitial");
String securityAuthentication = MapUtils.getString(ldapInfo, "securityAuthentication");
String securityPrincipal = MapUtils.getString(ldapInfo, "securityPrincipal");
String securityCredentials = MapUtils.getString(ldapInfo, "securityCredentials");
Long timeOut = MapUtils.getLongValue(ldapInfo, "timeOut", 3000L);
Hashtable<String, String> env = new Hashtable<String, String>();
//记录工JNDI工厂
env.put(Context.INITIAL_CONTEXT_FACTORY, factoryInitial);//com.sun.jndi.ldap.LdapCtxFactory
//LDAP的地址,要根据LDAP服务器IP进行修改,389是LDAP的默认端口
env.put(Context.PROVIDER_URL, providerUrl + baseDn);//ldap://10.182.136.11:389/DC=nsemii,DC=com
//默认授权类型,一般不用改
env.put(Context.SECURITY_AUTHENTICATION, securityAuthentication);//simple
//LDAP的账户名,一般是这样的格式:dc=hisi,dc=huawei,dc=com
env.put(Context.SECURITY_PRINCIPAL, securityPrincipal);//FA_ReportAdmin@nsemii.com
//密码
env.put(Context.SECURITY_CREDENTIALS, securityCredentials);//FAA411faa
env.put("com.sun.jndi.ldap.connect.timeout", timeOut.toString());
env.put("com.sun.jndi.ldap.read.timeout", timeOut.toString());
// 链接ldap
LdapContext ctx = new InitialLdapContext(env, null);
logger.info("LDAP认证服务连接成功....");
return ctx;
}
public static String authenticate(String usr, String pwd, Map<String, Object> ldapInfo) {
String principalSuffix = MapUtils.getString(ldapInfo, "principalSuffix");
LdapContext ctx = null;
try {
ctx = getCtx(ldapInfo);
} catch (NamingException e1) {
logger.error(e1);
return "Ldap Server connect error!";
}
try {
ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, usr + principalSuffix);
ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, pwd);
ctx.reconnect(null);
return "";
} catch (NamingException e) {
logger.error(e);
return "Ldap login authenticate error!";
} finally {
closeCtx(ctx);
}
}
public static List<Object> getUserKey(String usr, Map<String, Object> ldapInfo) throws Exception {
logger.info("****---> 需要查询的ad信息:{}", usr);
ArrayList<Object> resultList = new ArrayList<>();
LdapContext ldapContext = getCtx(ldapInfo);
if (ldapContext != null) {
String company = "";
String result = "";
try {
// 域节点
String searchBase = MapUtils.getString(ldapInfo, "searchDn");
// cn=*name*模糊查询 cn=name 精确查询
String searchFilter = "(objectclass=user)";
// 创建搜索控制器
SearchControls searchCtls = new SearchControls();
String returnedAtts[] = {"sAMAccountName", "cn", "givenName", "sn", "displayName", "mail", "entryUUID"};
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()) {
++rows;
// 得到符合搜索条件的DN
SearchResult sr = (SearchResult) answer.next();
String dn = sr.getName();
logger.info("****---> DN: " + dn);
//符合条件的属性集
Attributes Attrs = sr.getAttributes();
logger.info("***--->>>Attributes: " + JsonUtils.toString(Attrs));
if (Attrs != null) {
try {
for (NamingEnumeration ne = Attrs.getAll(); ne.hasMore(); ) {
Attribute Attr = (Attribute) ne.next();
logger.info("***--->>>Attribute: " + JsonUtils.toString(Attr));
// 读取属性值
for (NamingEnumeration e = Attr.getAll(); e.hasMore(); totalResults++) {
company = e.next().toString();
Map<String, Object> tempJson = new HashMap<>();
tempJson.put(Attr.getID(), company.toString());
resultList.add(tempJson);
}
}
} catch (NamingException e) {
logger.info("****---> Throw Exception : " + e.getMessage());
}
}
}
logger.info("****---> 总共用户数:" + rows);
} catch (NamingException e) {
logger.error("****---> Throw Exception : " + e.getMessage());
} finally {
try {
ldapContext.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
logger.info("***--->>>getUserKey返回的结果: " + JsonUtils.toString(resultList));
return resultList;
}
public static Map searchUserInfo(String usr, Map<String, Object> ldapInfo) throws Exception {
Map resultMap = new HashMap();
LdapContext ctx = getCtx(ldapInfo);
String result = "";
String baseDn = MapUtils.getString(ldapInfo, "searchDn");
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration<?> en = ctx.search(baseDn, "sAMAccountName=" + usr, constraints);
if (en == null) {
result += "Have no NamingEnumeration. \n";
resultMap.put("msg", result);
}
if (!en.hasMoreElements()) {
result += "Have no element. \n";
resultMap.put("msg", result);
}
while (en != null && en.hasMoreElements()) {
Object obj = en.nextElement();
if (obj instanceof SearchResult) {
SearchResult sr = (SearchResult) obj;
Attributes attrs = sr.getAttributes();
String sn = attrs.get("sn") + "";
String givenName = attrs.get("givenName") + "";
String mail = attrs.get("mail") + "";
String localName =
sn.substring(sn.indexOf(":") + 1).trim() + givenName.substring(givenName.indexOf(":")).trim();
resultMap.put("mail", mail.substring(mail.indexOf(":") + 1).trim());
resultMap.put("localName", localName);
} else {
logger.info(obj);
}
}
return resultMap;
}
/**
* @param ldappath 本级条目路径,如:dc=cs,dc=hunan,dc=com
* @param attrname 用于过滤的属性名,即条目包含该属性,可为空串
* @param attrval 用于过滤的属性值,即上面的属性包含该属性值,可为空串
* <p>
* 注意,当attrname为空串时,将忽略attrval 这个函数会返回NamingEnumeration对象,通过这个对象,我们可以遍历出所有搜索到的结果
* @return
*/
public static NamingEnumeration<Object> searchSubEntry(DirContext ctx, String ldappath, String attrname,
String attrval) {
NamingEnumeration ret = null;
if (ctx != null) {
try {
//先判断一下这个条目是不是存在
if (isExist(ctx, ldappath)) {
logger.info("***>>>目录存在,开始搜索");
//设定搜索条件 建一个属性集合对象
Attributes matchAttrs = new BasicAttributes(true);
//如果传入了属性名称条件就加到属性集合里
if (StringUtils.isNotBlank(attrname)) {
logger.info("***>>>添加了过滤属性名称{}", attrname);
matchAttrs.put(new BasicAttribute(attrname, attrval));
}
//搜索符合条件的结果
NamingEnumeration answer = ctx.search(ldappath, matchAttrs);
logger.info("***>>>搜索到的符合条件的结果: ", JsonUtils.toString(answer));
ret = answer;
}
logger.info("***>>>{}目录不存在", ldappath);
} catch (NamingException ex) {
ret = null; //出现异常时会返回null
logger.error(ex);
}
}
return ret;
}
public static boolean isExist(DirContext ldapCtx, String ldappath) {
try {
ldapCtx.search(ldappath, null); //测试检索一下
return true; //表示这个条目是存在的
} catch (NamingException ex) {
return false;
}
}
public static void closeCtx(LdapContext ctx) {
try {
ctx.close();
} catch (NamingException ex) {
logger.error(ex);
}
}
}