基础知识介绍
请参考其他资料:AD域介绍与配置 - 云淡风轻~江哥 - 博客园
废话不多说---上代码
使用maven生成工程
mvn archetype:generate -DinteractiveMode=false -DgroupId=com.dilusense.ad -DartifactId=AD -Dversion=1.0.0-SNAPSHOT
pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dilusense.ad</groupId>
<artifactId>AD</artifactId>
<packaging>jar</packaging>
<version>1.0.0-SNAPSHOT</version>
<name>AD</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>2.6.4</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
App.java 文件
package com.dilusense.ad;
import org.springframework.stereotype.Component;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
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 java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
//package com.cy.sendmail.util;
/**
* @author fd
* @title: getInfoFromAD
* @projectName DemoForADDomain
* @description: 通过LDAP从AD域获取信息
* @date 2022/8/31 13:36
*/
@Component
class GetInfoFromAD {
public void setCtx(LdapContext ctx) {
this.ctx = ctx;
}
//@Value("${ADServer.ip}")
private String ip;
//@Value("${ADServer.port}")
private String port;
//@Value("${ADServer.adminName}")
private String adminName;
//@Value("${ADServer.pwd}")
private String pwd;
//@Value("${ADServer.searchBase}")
private String searchBase;
private LdapContext ctx = null;
public void setIp(String ip) {
this.ip = ip;
}
public void setPort(String port) {
this.port = port;
}
public void setAdminName(String adminName) {
this.adminName = adminName;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public void setSearchBase(String searchBase) {
this.searchBase = searchBase;
}
public static void main(String[] args) throws Exception {
try {
GetInfoFromAD obj = new GetInfoFromAD();
obj.setIp("10.0.1.183");
obj.setPort("389");
obj.setAdminName("dilusense\\administrator");
obj.setPwd("Dl1u$ense");
//obj.setSearchBase("OU=X,CN=administrator,=DC=administrator");//DC=aadsync.dilusense.com
obj.setSearchBase("OU=X,DC=dilusense,DC=com");
obj.ldap_connect();
obj.getUserInfo();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 用户认证
*/
public void ldap_connect() {
String url = "ldap://" + ip + ":" + port;
System.out.println("url" + url);
Hashtable hashEnv = new Hashtable();
// LDAP安全访问级别,"none", "simple", "strong"
hashEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
// 管理员账号密码
hashEnv.put(Context.SECURITY_PRINCIPAL, adminName);
hashEnv.put(Context.SECURITY_CREDENTIALS, pwd);
// LDAP工厂类
hashEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
hashEnv.put(Context.PROVIDER_URL, url);
try {
ctx = new InitialLdapContext(hashEnv, null);
System.out.println("域控认证成功");
} catch (Exception e) {
System.out.println("域控认证失败");
e.printStackTrace();
}
}
/**
* 关闭连接
*/
public void ldap_close(){
try{
if(ctx != null) {
ctx.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
/**
* 获取域控用户信息
*/
public List getUserInfo() {
int i = 0;
// 用户信息稽核
List userList = new ArrayList<>();
// 域节点,CN-用户,OU-组,DC-域
String searchBase = this.searchBase;
// LDAP搜索过滤器类
String searchFilter = "objectClass=User";
// 搜索控制器
SearchControls searchCtls = new SearchControls();
// 创建搜索控制器
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
// 设置返回的用户属性,可以不设置,用户返回属性会很多
String returnedAtts[] = {"memberOf", "name", "mail", "userPrincipalName", "pwdlastset", "lockoutTime", "useraccountcontrol"};
// 设置返回属性集
searchCtls.setReturningAttributes(returnedAtts);
try{
System.out.println("ctx.search");
// 根据设置的域节点、过滤器类和搜索控制器搜索LDAP得到结果
NamingEnumeration answer = ctx.search(searchBase, searchFilter, searchCtls);
System.out.println("ctx.search2");
// 遍历结果
while (answer.hasMore()) {
ADUser user = new ADUser(); // 定义用户
SearchResult sr = (SearchResult) answer.next();// 根据查询属性返回查询结果
Attributes attrs = sr.getAttributes();// 得到符合条件的属性集
// 获取对象属性
Attribute name = attrs.get("name"); // 用户中文名
System.out.println(++i + "用户中文名:");
System.out.println(name);
user.setDisplayName(name.get().toString());
Attribute mail = attrs.get("mail"); // 用户邮箱
System.out.println(mail);
user.setMail(mail == null ? "" : mail.get().toString());
Attribute pwdLastSet = attrs.get("pwdlastset"); // 上次密码修改时间
user.setPwdLastSet(adExpiresToDate(Long.valueOf(pwdLastSet.get().toString()))); // 进行字符戳转换后赋值
Attribute uac = attrs.get("useraccountcontrol");// 用户控制,用于判断用户密码是否永不过期,该属性详情参考上面链接
user.setUserAccountControl(uac.get().toString());
if(!user.getMail().equals("")) { // 有邮箱,且密码设置了非永久不过期的账号
userList.add(user);
System.out.println(++i + "----" +user.toString());
}
}
}catch(Exception e){
e.printStackTrace();
}
return userList;
}
/**
* AD账户时间戳转换,windows NT时间转Date
* @param pwdLastSet
* @return
*/
public Date adExpiresToDate(long pwdLastSet){
long timeStamp = pwdLastSet - 116445312000000000L;
timeStamp = Long.parseLong(String.valueOf(timeStamp).substring(0, 13)) + 57599875L;
return new Date(timeStamp);
}
}
class ADUser {
private String displayName;
private String mail;
private String userAccountControl;
private Date pwdLastSet;
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
public String getUserAccountControl() {
return userAccountControl;
}
public void setUserAccountControl(String userAccountControl) {
this.userAccountControl = userAccountControl;
}
public Date getPwdLastSet() {
return pwdLastSet;
}
public void setPwdLastSet(Date pwdLastSet) {
this.pwdLastSet = pwdLastSet;
}
}
代码中 SearchBase 如何设置
打开AD域服务界面
打开步骤 打开 Active Directory 用户和计算机 单击“开始”,再单击“运行”。 在“打开”框中,键入 dsa.msc,再单击“确定”。 —或者— 单击“开始”,指向“所有程序”,再指向“Microsoft Exchange”,然后单击“Active Directory 用户和计算机”。如下界面:
DC:域控制器, 就是一台服务器,负责每一台联入网络的电脑和用户的验证工作。
OU:组织单元
所以, SearchBase="OU=X,DC=dilusense,DC=com",两个DC,不能合并,顺序也不能变。
另:windows出于安全的考虑,域用户的密码只能修改,不能获取。