// 配置属性
ldap.url=ldaps://****:1234
ldap.searchBase=OU=users123,DC=zz,DC=zzzz
ldap.groupBase=OU=xxxx,OU=yyyyy,DC=zz,DC=zzzz
ldap.loginMod=simple
ldap.username=test1234
# 密码不能明文,AES加密
ldap.password=aoodI9SUcgdFjv2pOdr2WA==
// 工具类
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import org.apache.commons.codec.binary.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LdapUtils {
private static Logger logger=LoggerFactory.getLogger(LdapUtils.class);
public static String msg = null;
private static String ldapUrl = new PropertiesUtil().readProperty("ldap.url");
private static String searchBase = new PropertiesUtil().readProperty("ldap.searchBase");
private static String mod = new PropertiesUtil().readProperty("ldap.loginMod");
private static String username = new PropertiesUtil().readProperty("ldap.username");
private static String password = new PropertiesUtil().readProperty("ldap.password");
/**
* 根据AD Account 获取用户信息
* @param adAccount
* @return
*/
@SuppressWarnings("unchecked")
public static Map<String,Object> getLdapUserInfo(String adAccount) {
Map<String,Object> map = null;
try {
//1、使用应用帐户登录,查询staffid对应的用户信息,和组信息
if(!username.contains("@")){
username=username+"@hsbc";
}
LdapContext ldap = openConnection(mod, ldapUrl, username, StringUtils.newStringUtf8( EncodeUtil.decrypt(password).getBytes() ) );
if(null!=ldap ){
logger.info("LDAP - API账号验证成功。");
// 查询的过滤条件,使用staffid查询用户信息
String userFilter="(name="+adAccount+")";
// 说明:AD中的每个属性都以 英文逗号 分割
// 返回的实际类型 为:List<Map<String,String[]>>
// 即:[{ key1=[value1],key2=[value1,value2,value3] }]
// 未过滤字段的返回结果
List<Object> rsList0= queryLdap(ldap, searchBase, userFilter, "one level", null);
logger.debug(">> LDAP-返回结果如下 ---------------- ");
Map<String,Object> map0=(Map<String,Object>)rsList0.get(0);
for( Map.Entry<String, Object> entry:map0.entrySet() ){
logger.debug("{}={}",entry.getKey(),entry.getValue());
}
// 过滤返回字段
String[] userAttrs=new String[]{
"name", // AD 账号:user12345
"mail", // 邮箱地址:user12345@text.com.cn
"Dn", // CN=user12345,OU=HSBCPeople,DC=z,DC=zz,DC=zzz
"company", // 公司名称
"personalTitle", // 称谓(MR=先生/女士):MR
"jpegPhoto", // 用户头像(二进制字段,binary blob)
"memberOf" // 所有角色列表(Dn),分号分割
};
List<Object> rsList = queryLdap(ldap, searchBase, userFilter, "one level", userAttrs);
if( null!=rsList && !rsList.isEmpty() ){
// 所有属性转为Map对象(值为数组形式),直接可以取值
map=(Map<String,Object>)rsList.get(0);
}
}
} catch (Exception e) {
}
return map;
}
/**
* 建立新的LDAP数据连接
* @author 45027834
* */
public static LdapContext openConnection(String mode,String url,String username,String password){
msg=null;
LdapContext ldapCxt=null;
try {
Hashtable<String, String> env = new Hashtable<String,String>();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION,mode);
env.put(Context.PROVIDER_URL,url);
env.put(Context.SECURITY_PRINCIPAL,username);
env.put(Context.SECURITY_CREDENTIALS,password);
env.put("java.naming.ldap.attributes.binary","objectSid objectGUID");
ldapCxt = new InitialLdapContext(env, null);
} catch (Exception e) {
msg = getErrorMsg(e.getMessage());
logger.error( "LDAP验证失败!"+e.getMessage(),e);
}
return ldapCxt;
}
/**
* 处理LDAP错误码
* @param exceptionMessage
* @return
*/
private static String getErrorMsg(String exceptionMessage) {
String msg = "AD validation failed.";
if( null!= exceptionMessage){
if( exceptionMessage.contains("error code 49") ){
msg = "AD account or password is wrong.";
}
else if( exceptionMessage.contains("error code 53") ){
msg = "AD password does not meet password policy.";
}
}
return msg;
}
/**
* 关闭LDAP数据库连接
* @author 45027834
* @param LdapContext Ldap数据库连接
* */
public static void closeConnection(LdapContext ldapCxt){
if(null!=ldapCxt){
try {
ldapCxt.close();
} catch (NamingException e) {
logger.error(e.getMessage(),e);
}
}
}
/**
* 根据传入的searchBase和filter查询信息,查询结果以List<Map<String,List<Object>>>的结构返回,其中Map的key由String[]中的元素提供
* @author 45027834
* @param LdapContext Ldap连接实例
* @param String 查询filter过滤器
* @param String seacherBase查询目录节点
* @param String[] attrs需要查询的要素名集合,如果一个字段在该数组中存在,在节点属性中不存在则不会生效
* */
public static List<Object> queryLdap(LdapContext ldapCtx,String searchBase,String filter,String scope,String[] attrs){
if(ldapCtx!=null){
try {
SearchControls sc = new SearchControls();
if(scope.equals("base")){
sc.setSearchScope(SearchControls.OBJECT_SCOPE);
}else if(scope.equals("one level")){
sc.setSearchScope(SearchControls.ONELEVEL_SCOPE);
}else{
sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
}
sc.setReturningAttributes(attrs);
NamingEnumeration<?> list = ldapCtx.search(searchBase, filter,sc);
List<Object> result = new ArrayList<Object>();
while(list.hasMore()){
SearchResult sr = (SearchResult) list.next();
Attributes attributes = sr.getAttributes();
NamingEnumeration<?> ne = attributes.getAll();
Map<String, Object> resultMap = new HashMap<String, Object>();
while(ne.hasMore()){
Attribute attribute =(Attribute) ne.next();
String attrType= attribute.getID();
NamingEnumeration<?> values=attribute.getAll();
List<Object> arr = new ArrayList<Object>();
while(values.hasMore()){
arr.add(values.nextElement());
}
resultMap.put(attrType,arr);
}
result.add(resultMap);
}
return result;
} catch (NamingException e) {
logger.info(e.getMessage(),e);
return null;
}
}
logger.info("LDAP连接为空");
return null;
}
}