先附上官方文档地址
https://docs.microsoft.com/en-us/windows/desktop/ad/polling-for-changes-using-the-dirsync-control
import com.sun.jndi.ldap.ctl.DirSyncControl;
import com.sun.jndi.ldap.ctl.DirSyncResponseControl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.Control;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import java.io.IOException;
import java.util.Hashtable;
import java.util.concurrent.TimeUnit;
public class Demo {
private static Logger logger = LoggerFactory.getLogger(Demo.class);
public static void main(String[] args) throws InterruptedException, NamingException, IOException {
modificationDetect();
}
/**
* @throws NamingException
* @throws IOException
* @throws InterruptedException
*/
public static void modificationDetect() throws NamingException, IOException, InterruptedException {
//连接配置
Hashtable<Object, Object> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "test@owo.com");
env.put(Context.SECURITY_CREDENTIALS, "123");
env.put(Context.PROVIDER_URL, "ldap://172.16.1.222:389");
LdapContext ctx = new InitialLdapContext(env, null);
SearchControls searchCtls = new SearchControls();
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
//搜索过滤
String searchFilter = "(&(objectClass=user)(objectCategory=person))";
String searchBase = "DC=owo,DC=com";
byte[] cookie;
int totalResults = 0;
int page = 0;
//第一次不传cookie
ctx.setRequestControls(new Control[]{new DirSyncControl()});
NamingEnumeration answer = ctx.search(searchBase, searchFilter, searchCtls);
cookie = retrieveCookie(ctx);
//windows ad 默认单次结果返回1000条记录,所以得不断遍历
while (answer.hasMoreElements()) {
page++;
while (answer.hasMoreElements()) {
SearchResult entry = (SearchResult) answer.next();
totalResults++;
logger.info("初始化被跟踪的User: " + entry.getName());
}
cookie = retrieveCookie(ctx);
ctx.setRequestControls(new Control[]{new DirSyncControl(1, Integer.MAX_VALUE, cookie, true)});
answer = ctx.search(searchBase, searchFilter, searchCtls);
}
logger.info("初始化总数:{};页数:{}", totalResults, page);
ctx.close();
ctx = new InitialLdapContext(env, null);
//获取到cookie后,以下是轮询,每次轮询完后更新cookie
while (true) {
TimeUnit.SECONDS.sleep(2);
totalResults = 0;
//每次轮询都传入上次更新过的cookie
ctx.setRequestControls(new Control[]{new DirSyncControl(1, Integer.MAX_VALUE, cookie, true)});
answer = ctx.search(searchBase, searchFilter, searchCtls);
while (answer.hasMoreElements()) {
SearchResult sr = (SearchResult) answer.next();
totalResults++;
//rDn
logger.info("rDn:{} ", sr.getName());
final Attributes attrs = sr.getAttributes();
if (attrs != null) {
//处理修改
for (NamingEnumeration<? extends Attribute> names = attrs.getAll(); names.hasMore(); ) {
Attribute attr = names.next();
if (attr.getAll().hasMore()) {
System.out.println(attr.getID() + " : " + attr.get());
}
}
}
}
logger.info("新修改:{} ", totalResults);
//更新cookie
cookie = retrieveCookie(ctx);
}
}
/**
* 取出cookie
*
* @param ctx
* @return
* @throws NamingException
*/
private static byte[] retrieveCookie(LdapContext ctx) throws NamingException {
Control[] controls;
if ((controls = ctx.getResponseControls()) != null) {
for (int i = 0; i < controls.length; i++) {
if (controls[i] instanceof DirSyncResponseControl) {
DirSyncResponseControl dirSyncResponseControl = (DirSyncResponseControl) controls[i];
return dirSyncResponseControl.getCookie();
}
}
}
return new byte[0];
}
}