Active directory 检索大型广告组的所有成员

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=

使用Microsoft Active Directory和未绑定SDK时,有一个组的成员数>29k

我试图利用范围值来获取所有组,但无法确定何时到达终点

我正在使用此方法:(更新为工作代码)

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.
}