需求需要在登录时连接Windows AD域控进行登录验证,结合前人代码整理改造为项目可用的状态,仅做记录
package com.sinosoft.microservice.product.manage.config.security.impl;
import com.sinosoft.microservice.product.manage.config.utils.ConfigStaticConstant;
import com.sinosoft.microservice.product.manage.config.utils.EscapeUtil;
import lombok.extern.slf4j.Slf4j;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.SearchControls;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import java.util.Hashtable;
/**
* @Author hsp
* @Date 2023-05-29
* @Company
* @Description
* @Param
* @return
*/
@Slf4j
public class ADAccountAuthority {
private int connectADDomain(Hashtable<String, String> HashEnv, String host) {
// 初始化用户结果集
// StringBuffer userPrincipalName = new StringBuffer();
// 初始化搜索结果数为0
int rows = 0;
try {
LdapContext ctx = new InitialLdapContext(HashEnv, null);
// 域节点
String searchBase = "DC=test,DC=com";
// LDAP搜索过滤器类
// String searchFilter = "objectClass=*";
String searchFilter = "objectClass=User";
// 创建搜索控制器
SearchControls searchCtls = new SearchControls();
// 设置搜索范围
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
// 定制返回属性 按需选择
//String[] returnedAtts = {"memberOf", "distinguishedName", "Pwd-Last-Set", "User-Password", "cn"};
//String[] returnedAtts = { "url", "whenChanged", "employeeID","name", "userPrincipalName", "physicalDeliveryOfficeName","departmentNumber", "telephoneNumber", "homePhone","mobile", "department", "sAMAccountName", "whenChanged","mail","objectClass" }; // 定制返回属性
String[] returnedAtts = {"name", "userPrincipalName", "distinguishedName"};
// 设置返回属性集
searchCtls.setReturningAttributes(returnedAtts);
EscapeUtil.safeLog(log, "******************* ADAccountCheck: AD配置设置完毕,尝试连接AD域控 ***********************");
// 根据设置的域节点、过滤器类和搜索控制器搜索LDAP得到结果
NamingEnumeration answer = ctx.search(searchBase, searchFilter, searchCtls);
//整个while遍历结果注释掉,直接看能不能联通,联通rows+1,判断时如果rows>1就返回true
if (answer.hasMoreElements()) {
rows++;
}
EscapeUtil.safeLog(log, "******************* ADAccountCheck: 当前host " + host + "登录通过,rows值为: " + rows + " ***********************");
/*while (answer.hasMoreElements()) {// 遍历结果集
SearchResult sr = (SearchResult) answer.next();// 得到符合搜索条件的DN
//System.out.println(sr.toString());
//System.out.println("Attributes: "+sr.getAttributes());
//System.out.println("userPrincipalName: "+sr.getAttributes().get("userPrincipalName"));
Attributes Attrs = sr.getAttributes();// 得到符合条件的属性集
if (Attrs != null && Attrs.get("userPrincipalName") != null) {
System.out.println(++rows + "************************************************");
System.out.println("Name: " + sr.getName());
try {
for (NamingEnumeration ne = Attrs.getAll(); ne.hasMore(); ) {
Attribute Attr = (Attribute) ne.next();// 得到下一个属性
System.out.println(" AttributeID=属性名:" + Attr.getID());
// 读取属性值
for (NamingEnumeration e = Attr.getAll(); e.hasMore(); ) {
String value = e.next().toString();
System.out.println(" AttributeValues=属性值:" + value);
// 使用堡垒机登陆成功了114,但是没有拿到登录账号的数据,排查下是不是这里的问题
if ("userPrincipalName".equals(Attr.getID())) {
userPrincipalName.append(value);
userPrincipalName.append(",");
}
}
System.out.println(" ---------------");
// 读取属性值
// Enumeration values = Attr.getAll();
// if (values != null) { // 迭代
// while (values.hasMoreElements()) {
// System.out.println(" AttributeValues=属性值:"+
// values.nextElement());
// }
// }
// System.out.println(" ---------------");
}
} catch (NamingException e) {
System.err.println("Throw Exception : " + e);
}
}
}*/
//System.out.println("************************************************");
//System.out.println("TotalResults: " + rows);
//EscapeUtil.safeLog(log, "******************* ADAccountCheck: 当前host " + host + "所有结果数 " + rows + " ***********************");
//EscapeUtil.safeLog(log, "******************* ADAccountCheck: All ADAccount at host " + host + userPrincipalName.toString() + " ***********************");
//System.out.println("域控所有账户: " + userPrincipalName.toString());
ctx.close();
} catch (NamingException e) {
e.printStackTrace();
//System.err.println("Throw Exception : " + e);
EscapeUtil.safeError(log, "**************************ADAccountCheck: NamingException at host " + host + " **************************");
}
return rows;
}
public boolean checkAD(String userName, String password) {
EscapeUtil.safeLog(log, "******************* Start ADAccountCheck v3 ***********************");
EscapeUtil.safeLog(log, "******************* ADAccountCheck: AD域账户: " + userName + "" + " AD域密码: " + password + " ***********************");
//初始化host列表
String[] hosts = new String[]{ConfigStaticConstant.ADHOST_HKHKG1_DC01, ConfigStaticConstant.ADHOST_HKHKG1_DC02, ConfigStaticConstant.ADHOST_HKHKG2_DC01, ConfigStaticConstant.ADHOST_SGSIN1_DC01};
for (String host : hosts) {
EscapeUtil.safeLog(log, "******************* ADAccountCheck: Try to connect host " + host + " ***********************");
String port = ConfigStaticConstant.LDAP_PORT; // 端口
String domain = ConfigStaticConstant.DOMAIN; // 域名
String url = "ldap://" + host + ":" + port;
String user = userName + domain;
Hashtable<String, String> hashEnv = new Hashtable<>();
hashEnv.put(Context.SECURITY_AUTHENTICATION, "simple"); // LDAP访问安全级别
hashEnv.put(Context.SECURITY_PRINCIPAL, user); // AD User
hashEnv.put(Context.SECURITY_CREDENTIALS, password); // AD Password
hashEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); // LDAP工厂类
hashEnv.put(Context.PROVIDER_URL, url);
if (connectADDomain(hashEnv, host) > 0) {
return true;
}
//下面这个是添加所有结果的,现在只测试连通性
// result.append(connectADDomain(hashEnv, host));
// if (result.length() != 0) {
// EscapeUtil.safeLog(log, "******************* ADAccountCheck: All ADAccount at host " + host + result + " ***********************");
// return result;
// }
}
EscapeUtil.safeLog(log, "******************* ADAccountCheck: AD域账户 :"+userName+" 登陆失败***********************");
return false;
}
}