2016-03-20 10 views
0

Yani, $adSearchFilter = "(&(objectCategory=User)(samAccountType:1.2.840.113556.1.4.803:=805306368)(SamAccountName='Account1')) gibi bir şey için ldap filtresini kullanarak bir hesap kapandığını biliyorum. Ldap filtresinin bir liste isminden geçmesine izin vermenin bir yolu var mı, = kullanmak yerine -contains gibi bir şey kullanabilir miyim? Aşağıda directordaearcher için ldap filtresindeki özellikleri listele

kodudur ve gördüğünüz gibi, ben $adSearchFilter += "($searchPropertyName=$searchPropertyValue)" gibi bir şey yapmayı düşündün bir foreach döngüsü tüm arama işlemi için bir seferde bir kullanıcı ...

Function GetUsersInfoFromDomain 
{ 
    Param ([String]$searchPropertyName, [String[]]$searchPropertyValues, [String[]]$DcWithCred,[String]$domainShortName, [String[]]$userProperties) 

    $queryTable = @() 
    ForEach ($searchPropertyValue in $searchPropertyValues) 
    { 
     $adSearchFilter = "(&(objectCategory=User)(samAccountType:1.2.840.113556.1.4.803:=805306368)($searchPropertyName=$searchPropertyValue))" 
     Write-Host "Searching domain $domainShortName with $searchPropertyName $searchPropertyValue" 
     $searchDomainResultsTable = powershell -command { 
      Param ([String]$adSearchFilter, [String[]]$userProperties,[String[]]$DcWithCred, [String]$domainShortName) 
      [string]$DC = $DcWithCred[0] 
      [string]$Username = $DcWithCred[1] 
      [string]$Password = $DcWithCred[2] 
      [string]$domain = "LDAP://$DC" 

      $adDomain = New-Object System.DirectoryServices.DirectoryEntry($domain, $Username, $Password) 
      $adSearcher = New-Object System.DirectoryServices.DirectorySearcher($adDomain) 
      $adSearcher.Filter = $adSearchFilter 
      $adSearcher.PageSize=1000 
      $adSearcher.PropertiesToLoad.AddRange($userProperties) | out-Null 
      $userRecords = $adSearcher.FindAll() 
      $adSearcher.Dispose() | Out-Null 
      [System.GC]::Collect() | Out-Null 

      # The AD results are converted to an array of hashtables. 
      $userPropertiesTable = @() 
      foreach($record in $userRecords) { 
       $hashUserProperty = @{} 
       foreach($userProperty in $userProperties){ 
        if (($userProperty -eq 'objectGUID') -or ($userProperty -eq 'objectSid') -or ($userProperty -eq 'msExchMasterAccountSid')) { 
         if ($record.Properties[$userProperty]) { 
          $hashUserProperty.$userProperty = $record.Properties[$userProperty][0] 
         } else { 
         $hashUserProperty.$userProperty = $null 
         } 
        } Else { 
         if ($record.Properties[$userProperty]) { 
          $hashUserProperty.$userProperty = ($record.Properties[$userProperty] -join '; ').trim('; ') 
         } else { 
         $hashUserProperty.$userProperty = $null 
         } 
        } #end Else 
       } #end ForEach 
       $userPropertiesTable += New-Object PSObject -Property $hashUserProperty 
      } #end ForEach 
      [System.GC]::Collect() | Out-Null 

      # Fixes the property values to be a readable format before exporting to csv file 
      $listOfBadDateValues = '9223372036854775807', '9223372036854770000', '0' 
      $maxDateValue = '12/31/1600 5:00 PM' 
      $valuesToFix = @('lastLogonTimestamp', 'AccountExpires', 'LastLogon', 'pwdLastSet', 'objectGUID', 'objectSid', 'msExchMasterAccountSid') 
      $extraPropertyValues = @('Domain Name') 
      $valuesToFixCounter = 0 
      $extraPropertyValuesCounter = 0 
      $valuesToFixFound = @($false, $false, $false, $false, $false, $false, $false) 
      $extraPropertyValuesFound = @($false) 

      ForEach ($valueToFix in $valuesToFix) 
      { 
       if ($userProperties -contains $valueToFix) 
       { 
        $valuesToFixFound[$valuesToFixCounter] = $true 
       } 
       $valuesToFixCounter++ 
      } 

      ForEach ($extraPropertyValue in $extraPropertyValues) 
      { 
       if ($userProperties -contains $extraPropertyValue) 
       { 
        $extraPropertyValuesFound[$extraPropertyValuesCounter] = $true 
       } 
       $extraPropertyValuesCounter++ 
      } 

      $tableFixedValues = $userPropertiesTable | % { 
       if ($valuesToFixFound[0]) { 
        if ($_.lastLogonTimestamp) { 
         $_.lastLogonTimestamp = ([datetime]::FromFileTime($_.lastLogonTimestamp)).ToString('g') 
        } 
       }; if ($valuesToFixFound[1]) { 
        if (($_.AccountExpires) -and ($listOfBadDateValues -contains $_.AccountExpires)) { 
         $_.AccountExpires = "" 
        } else { 
         if (([datetime]::FromFileTime($_.AccountExpires)).ToString('g') -eq $maxDateValue) { 
          $_.AccountExpires = "" 
         } Else { 
          $_.AccountExpires = ([datetime]::FromFileTime($_.AccountExpires)).ToString('g') 
         } 
        } 
       }; if ($valuesToFixFound[2]) { 
        if (($_.LastLogon) -and ($listOfBadDateValues -contains $_.LastLogon)) { 
         $_.LastLogon = "" 
        } else { 
         if (([datetime]::FromFileTime($_.LastLogon)).ToString('g') -eq $maxDateValue) { 
          $_.LastLogon = "" 
         } Else { 
          $_.LastLogon = ([datetime]::FromFileTime($_.LastLogon)).ToString('g') 
         } 
        } 
       }; if ($valuesToFixFound[3]) { 
        if (($_.pwdLastSet) -and ($listOfBadDateValues -contains $_.pwdLastSet)) { 
         $_.pwdLastSet = "" 
        } else { 
         if (([datetime]::FromFileTime($_.pwdLastSet)).ToString('g') -eq $maxDateValue) { 
          $_.pwdLastSet = "" 
         } Else { 
          $_.pwdLastSet = ([datetime]::FromFileTime($_.pwdLastSet)).ToString('g') 
         } 
        } 
       }; if ($valuesToFixFound[4]) { 
        if ($_.objectGUID) { 
         $_.objectGUID = ([guid]$_.objectGUID).Guid 
        } Else { 
         $_.objectGUID = "" 
        } 
       }; if ($valuesToFixFound[5]) { 
        if ($_.objectSid) { 
         $_.objectSid = (New-Object Security.Principal.SecurityIdentifier($_.objectSid, 0)).Value 
        } Else { 
         $_.objectSid = "" 
        } 
       }; if ($valuesToFixFound[6]) { 
        if ($_.msExchMasterAccountSid) { 
         $_.msExchMasterAccountSid = (New-Object Security.Principal.SecurityIdentifier($_.msExchMasterAccountSid, 0)).Value 
        } Else { 
         $_.msExchMasterAccountSid = "" 
        } 
       }; If ($extraPropertyValuesFound[0]) { 
        If (!($_.'Domain Name')) { 
         $_.'Domain Name' = $domainShortName 
        } 
       };$_} 
       [System.GC]::Collect() | Out-Null 

       $sortedTableColumns = $tableFixedValues | Select-Object $userProperties 
       [System.GC]::Collect() | Out-Null 

       return $sortedTableColumns 
     } -args $adSearchFilter, $userProperties, $DcWithCred, $domainShortName 
     [System.GC]::Collect() | Out-Null 
     Write-Host "Search Complete." 
     Write-Host "" 

     if ($searchDomainResultsTable) 
     { 
      $queryTable += $searchDomainResultsTable 
     } 
    } # End ForEach Loop 
    Write-Host 'Exporting domain search results to table...' 
    Write-Output $queryTable 
} 

arar. Ancak 10mb limiti nedeniyle - What is the LDAP filter string length limit in Active Directory?, bu 200.000 ++ kullanıcı ararken en iyi yöntem olacağını emin değilim.

Arama başına 1 dize değeri yerine bir listeyi geçmenin bir yolu bilen var mı?

+1

Neden aynı aramada 200000 + belirli kullanıcılara filtre uyguladınız? –

+0

etki alanındaki 1mil + dışında, diğer çeşitli uygulamalarda ve veritabanlarında eşleşen özellikler arıyordum. –

cevap

1

LDAP bir -contains benzeri deyimi yoktur, ancak birden çok kesin değerlerle eşleşen bir filtre ifadesini oluşturmak için VEYA operatörü (|) kullanabilirsiniz:

(|(samaccountname=user1)(samaccountname=user2)(samaccountname=user3)) 

Bu benim kuracağına nasıl filtre dizesi:

söyleniyor
$FilterTemplate = '(&(objectCategory=User)(samAccountType:1.2.840.113556.1.4.803:=805306368){0})' 
$ClauseTemplate = "($searchPropertyName={0})" 
$AllClauses  = $searchPropertyValues |ForEach-Object { $ClauseTemplate -f $_ } 
$adSearchFilter = $FilterTemplate -f $($AllClauses -join '') 

, neden tek bir aramada aramak için 200000 belirli değerler geçerdi? LDAP joker eşleştirmeyi destekler (ör. (samaccountname=*)). Her durumda

, sen $AllClauses en büyük ipte Encoding.GetByteCount arayarak, sizin dize son boyutunu hesaplamak ve sonra diziyi bölme kullanabilirsin (en güvenli tarafta olmak üzere 9.5 MB yer o kap let) :

$LongestString = $AllClauses |Sort -Property Length |Select -Last 1 
$LongestByteCount = [System.Text.Encoding]::Unicode.GetByteCount($LongestString) 
if(($LongestByteCount * $AllClauses.Count) -gt 9.5MB) 
{ 
    $MaxCount = [int](9.5MB/$LongestByteCount) 
    for($i = 0; $i -lt $AllClauses.Count; $i += $MaxCount) 
    { 
     $ClauseSubset = $AllClauses[$i..$($i + $MaxCount - 1)] 
     $adSearchFilter = $FilterTemplate -f $($ClauseSubset -join '') 
     # Do your search 
    } 
} 
+0

Sorunuzun yanıtı, yukarıdaki yorumda verilmiştir. Bir for döngüsünü kullanarak 200.000 kere '(sadfjweoqifhnweqhfweqofhqe = hnqfkohwqopfnh2fh2qf023f0) bir dizi oluşturmak için küçük bir betik yazdım ve bir txt dosyasına aktardım. Dosya 10.5 m uzunluğunda. Yani benim teorimin doğru olduğu anlaşılıyor (soruda). Ancak bunu bir koşul olarak kullanabilirim (eğer arama için büyük bir dizede 200.000’den daha az atmışsa, her bir kullanıcıyı bir seferde 1 arayabilir). –

+0

@FiddleFreak Yeterince adil, dize boyutunu hesaplamak ve diziyi uygun şekilde bölümlendirmek için bir örnekle güncellenmiş bir cevap –

+0

Teşekkürler bir demet :) –