Active directory 检索大型广告组的所有成员
使用Microsoft Active Directory和未绑定SDK时,有一个组的成员数>29k 我试图利用范围值来获取所有组,但无法确定何时到达终点 我正在使用此方法:(更新为工作代码)Active directory 检索大型广告组的所有成员,active-directory,ldap,unboundid-ldap-sdk,Active Directory,Ldap,Unboundid Ldap Sdk,使用Microsoft Active Directory和未绑定SDK时,有一个组的成员数>29k 我试图利用范围值来获取所有组,但无法确定何时到达终点 我正在使用此方法:(更新为工作代码) public static List getAttributeRangeBasedSearch(LDAPConnection ldc、String basedn、String filter、int step、String return_属性)抛出LDAPException { List allValues=
public static List getAttributeRangeBasedSearch(LDAPConnection ldc、String basedn、String filter、int step、String return_属性)抛出LDAPException
{
List allValues=new ArrayList();
//初始化计数器以合计组成员和范围值
int-allvalues=0;
int start=0;
//int步长=1000;
int finish=步骤-1;
布尔值finallyFinished=false;
字符串范围;
//循环查询,直到得到所有结果
而(!最终完成)
{
范围=开始+“-”+结束;
字符串currentRange=return_属性+“Range=“+Range;
字符串范围_returnedAtts[]={currentRange};
SearchRequest SearchRequest=新的SearchRequest(basedn、SearchScope.BASE、filter、range\u returnedAtts);
List rangedEntries=ldc.search(searchRequest.getSearchEntries();
for(Iterator Iterator=rangedEntries.Iterator();Iterator.hasNext();)
{
SearchResultEntry SearchResultEntry=iterator.next();
集合allAttribute=searchResultEntry.getAttributes();
for(迭代器attributeIterator=allAttribute.Iterator();attributeIterator.hasNext();)
{
Attribute=attributeIterator.next();
log.debug(“-->”+allvalues+:“+attribute.getName());
if(attribute.getName().endsWith(“*”))
{
currentRange=attribute.getName();
最终完成=真;
}
String[]attributeBatch=searchResultEntry.getAttributeValues(当前范围);
for(int i=0;i
有什么想法吗
谢谢
-jim我让事情运转起来,但这个过程非常困难,目前我正在使用一个硬编码的步骤值,因为它可以动态地从默认值1500更改为硬编码限制5000 我无法动态确定该值。如果未在以下位置定义:CN=查询策略、CN=目录服务、CN=Windows NT、CN=服务、CN=配置、林根,则必须为默认值,默认值也会根据使用的Microsoft Active Directory版本而有所不同 MSDN中也描述了这可能会有所帮助,但没有关于如何使用它的信息有人用过这个吗? LDAP策略是使用lDAPAdminLimits属性指定的 queryPolicy对象的lDAPAdminLimits属性是一个多值字符串,其中每个字符串值编码一个名称-值对。在编码中,名称和值用“=”分隔。例如,值为“0”的名称“MaxActiveQueries”的编码为“MaxActiveQueries=0”。每个名称都是LDAP策略的名称,该值是该策略的值。 AD林中可以有多个queryPolicy对象。DC根据以下逻辑确定包含其策略的queryPolicy对象:
- 如果DC的nTDSDSA对象上存在queryPolicyObject属性,则DC将使用其引用的queryPolicy对象
- 否则,如果DC所属的Active Directory站点的nTDSSiteSettings对象上存在queryPolicyObject属性,则DC将使用Active Directory站点引用的queryPolicy对象
- 否则,DC使用其DN相对于nTDSService对象为“CN=默认查询策略,CN=查询策略”的queryPolicy对象(例如,相对于配置NC的根,“CN=默认查询策略,CN=查询策略,CN=目录服务,CN=Windows NT,CN=服务”)
$myGroup = [string]$args[0];
$myGroup = $myGroup.replace(" ",",");
$group = [adsi]("LDAP://$($myGroup)");
$from = 0
$all = $false
$members = @()
while (! $all) {
trap{$script:all = $True;continue}
$to = $from + 999
$DS = New-Object DirectoryServices.DirectorySearcher($Group,"(objectClass=*)","member;range=$from-$to",'Base')
$members += $ds.findall() | foreach {$_.properties | foreach {$_.item($_.PropertyNames -like 'member;*')}}
if($from -gt $members.count){
break;
}
$from += 1000
}
$currentExecuting = (Get-Item $MyInvocation.MyCommand.Path)
$group.sAMAccountName
$members | measure-object
$members > "$($currentExecuting.Directory)\$($group.sAMAccountName).txt"
用法:
getADGroupMembers.ps1 CN=groupName,OU=myOrgUnit,DC=contoso,DC=com
下面是一个非常好的代码示例,您可以通过范围获取组的所有成员。当你在最后一个范围时,它也会处理这个问题。您还可以在分页请求中转换此方法。看一看。它帮助了我
try
{
DirectoryEntry entry = new DirectoryEntry("LDAP://CN=My Distribution List,OU=Distribution Lists,DC=Fabrikam,DC=com");
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.Filter = "(objectClass=*)";
uint rangeStep = 1000;
uint rangeLow = 0;
uint rangeHigh = rangeLow + (rangeStep - 1);
bool lastQuery = false;
bool quitLoop = false;
do
{
string attributeWithRange;
if(!lastQuery)
{
attributeWithRange = String.Format("member;range={0}-{1}", rangeLow, rangeHigh);
}
else
{
attributeWithRange = String.Format("member;range={0}-*", rangeLow);
}
searcher.PropertiesToLoad.Clear();
searcher.PropertiesToLoad.Add(attributeWithRange);
SearchResult results = searcher.FindOne();
foreach(string res in results.Properties.PropertyNames)
{
System.Diagnostics.Debug.WriteLine(res.ToString());
}
if(results.Properties.Contains(attributeWithRange))
{
foreach(object obj in results.Properties[attributeWithRange])
{
Console.WriteLine(obj.GetType());
if(obj.GetType().Equals(typeof(System.String)))
{
}
else if (obj.GetType().Equals(typeof(System.Int32)))
{
}
Console.WriteLine(obj.ToString());
}
if(lastQuery)
{
quitLoop = true;
}
}
else
{
lastQuery = true;
}
if(!lastQuery)
{
rangeLow = rangeHigh + 1;
rangeHigh = rangeLow + (rangeStep - 1);
}
}
while(!quitLoop);
}
catch(Exception ex)
{
// Handle exception ex.
}
来源:AD,默认情况下,每个属性最多只能存储5000个条目;如果有更多属性,则将属性拆分为多个“块”-
member0-4999代码>会员5000-9999代码>等等。你能把它们合并在一起得到完整的列表吗?或者,您可以执行分页搜索,询问memberOf属性包含组的可分辨名称的所有用户,但这比前一种方法慢。问题不在于条目,而是由MaxValRange确定的值,对于此实例,MaxValRange为每个属性1500。我得到了所有结果,但当我要求最后一组值时,它是一个部分大小,如member28131-?????从某种意义上说,我不知道是什么。因此,如何在每个结果中告诉范围的返回值。谢谢-Jimac事实上现在我记得分号正好在属性名之后,所以只需循环遍历所有检索到的属性,在分号上拆分它们的名称,并将所有同名属性合并在一起。所以我让它工作了,但这太难了,在LDAP标准中没有任何内容。是否有人知道如何使用此处描述的“已报告”控件:?此DN是正确的。对于ADLDS,DN是CN=默认查询策略,CN=查询策略,CN=目录服务,CN=Windows NT,CN=Services,CN=Configuration,CN=xxxxxxxxxx
。属性为lDAPAdminLimits
,其值为MaxValRange=5000
。号码是可调的。
try
{
DirectoryEntry entry = new DirectoryEntry("LDAP://CN=My Distribution List,OU=Distribution Lists,DC=Fabrikam,DC=com");
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.Filter = "(objectClass=*)";
uint rangeStep = 1000;
uint rangeLow = 0;
uint rangeHigh = rangeLow + (rangeStep - 1);
bool lastQuery = false;
bool quitLoop = false;
do
{
string attributeWithRange;
if(!lastQuery)
{
attributeWithRange = String.Format("member;range={0}-{1}", rangeLow, rangeHigh);
}
else
{
attributeWithRange = String.Format("member;range={0}-*", rangeLow);
}
searcher.PropertiesToLoad.Clear();
searcher.PropertiesToLoad.Add(attributeWithRange);
SearchResult results = searcher.FindOne();
foreach(string res in results.Properties.PropertyNames)
{
System.Diagnostics.Debug.WriteLine(res.ToString());
}
if(results.Properties.Contains(attributeWithRange))
{
foreach(object obj in results.Properties[attributeWithRange])
{
Console.WriteLine(obj.GetType());
if(obj.GetType().Equals(typeof(System.String)))
{
}
else if (obj.GetType().Equals(typeof(System.Int32)))
{
}
Console.WriteLine(obj.ToString());
}
if(lastQuery)
{
quitLoop = true;
}
}
else
{
lastQuery = true;
}
if(!lastQuery)
{
rangeLow = rangeHigh + 1;
rangeHigh = rangeLow + (rangeStep - 1);
}
}
while(!quitLoop);
}
catch(Exception ex)
{
// Handle exception ex.
}