我们正在编写允许 Active Directory 身份验证机制的软件工具。它会定期在 AD 和工具之间同步用户组。我们的一些客户发现,在同步操作期间,AD 服务器上的 CPU 负载很高。
我搜索了可能导致该问题的原因。其中之一是嵌套组。
此外,我在互联网上发现其他人也遇到过这样的问题,当他们更改 AD 端口时,问题就消失了。我想知道最后一种情况是否现实(对我来说,更改 AD 端口可以解决问题有点奇怪),以及是否还有其他常见原因可能导致该问题。
我们使用以下查询来同步:
(&(memberof:1.2.840.113556.1.4.1941:=group_DN)(objectclass=user)(!(objectclass=computer))
答案1
不要使用 LDAP 匹配规则传递评估来进行递归组成员身份评估。众所周知,这种方法非常慢,尤其是对于大型目录/组成员身份。
http://dunnry.com/blog/TransitiveLinkValueFilterEvaluation.aspx
https://stackoverflow.com/questions/9534669/improving-recursive-active-directory-function
答案2
所以事实证明问题确实出在嵌套组上。我将递归逻辑“移动”到客户端,将运行时间缩短了约 10 倍。我不知道网络流量会增加多少。无论如何,以下是我使用的代码片段,以防万一有人感兴趣:
public Set<String> getUsersInGroup(String groupDN) throws NamingException {
Set<String> ret = new HashSet<>();
Queue<String> bfsQueue = new LinkedList<>();
bfsQueue.add(groupDN);
Set<String> visitedGroups = new HashSet<>();
LdapContext ctx = getLdapContext(MAX_SEARCH_TIME, false);
String[] attrIDs = getUserReturnAttrs().toArray(new String[0]);
while (!bfsQueue.isEmpty()) {
String current = bfsQueue.element();
bfsQueue.remove();
visitedGroups.add(current);
String userFilter = "(&(objectclass=user)(!(objectclass=computer)))";
String groupFilter = "(&(objectclass=group)(!(objectclass=computer)))";
String memberOfFilter = String.format("(memberof=%s)", current);
String userQuery = String.format("(&%s%s)", memberOfFilter, userFilter);
String groupQuery = String.format("(&%s%s)", memberOfFilter, groupFilter);
Set<SearchResult> groups = search(ctx, getSearchBase(), groupQuery, SearchControls.SUBTREE_SCOPE,
new String[] { "distinguishedName" }, NO_COUNT_LIMIT);
for (SearchResult g : groups) {
Attributes attrs = g.getAttributes();
String gDN = parseAttribute(attrs, "distinguishedName");
if (!visitedGroups.contains(gDN)) bfsQueue.add(gDN);
}
Set<SearchResult> users = search(ctx, getSearchBase(), userQuery, SearchControls.SUBTREE_SCOPE,
attrIDs, NO_COUNT_LIMIT);
for (SearchResult u : users) {
Attributes attrs = u.getAttributes();
String uDN = parseAttribute(attrs, "userPrincipalName");
ret.add(uDN);
}
}
return ret;
}