用于检查组成员不工作的 PowerShell 函数

PowerShell Function to check group member not working

我发现这个函数我想在我正在编写的脚本中使用,但是当我看到一个帐户在一个组中时它总是返回 $false,但我不明白为什么?

function Check-IsGroupMember{

Param($user,$grp)

$strFilter = "(&(objectClass=Group)(name=" + $grp +"))"

$objDomain = New-Object System.DirectoryServices.DirectoryEntry

$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
 $objSearcher.SearchRoot = $objDomain
 $objSearcher.PageSize = 1000
 $objSearcher.Filter = $strFilter
 $objSearcher.SearchScope = "Subtree"

$colResults = $objSearcher.FindOne()

$objItem = $colResults.Properties
 ([string]$objItem.member).contains($user)

}
Usage:

Check-IsGroupMember "name of user" "DomainAdmins"

$objItem.member 包含作为组成员的每个主体的 DistinguishedName 值。

即使一个人的专有名称可能是 John Doe,用户帐户对象的通用名称仍然可能是 Doe, JohnJohn G. Doe 或其他任何名称。这意味着 Contains() 检查(这只是一个简单的子字符串搜索)不能保证按您预期的那样工作。

唯一真正的检查方法是 运行 对用户进行另一次搜索以找到 his/her DistinguishedName.

就个人而言,我会选择 RSAT 的 AD PowerShell 模块,而不是使用 DirectorySearcher:

function Test-GroupMembership 
{
  Param(
    [string]$UserName,
    [string]$GroupName
  )

  $User  = Get-ADUser -Identity $UserName
  $Group = Get-ADGroup -Identity $GroupName -Properties member

  $Group.member -contains $User.DistinguishedName
}

如果大小限制是您的问题,您可以使用 DirectoryServer 检索成员属性的 ranged result

function Test-GroupMembership 
{
  [CmdletBinding()]
  Param(
    [string]$UserName,
    [string]$GroupName
  )

  # Fetch User
  $User = Get-ADUser -Identity $UserName

  # return on failure
  if(-not $User){
    Write-Error -Message ('User "{0}" not found' -f $GroupName)
    return $false
  }

  # Use DirectorySearcher to retrieve ranged member attribute
  $GroupSearcher = '' -as [adsisearcher]
  $GroupSearcher.Filter = '(&(objectClass=group)(name={0}))' -f $GroupName
  $GroupSearcher.SearchScope = 'Subtree'
  $GroupSearcher.SearchRoot = '' -as [adsi]

  # AD reponds with at least 1500 values per multi-value attribute since Windows Server 2003
  $Start = 1
  $Range = 1500
  $GroupMembers = @()

  $HasMoreMembers = $false

  # Keep retrieving member values until we've got them all
  do{

    # Use range operator to "page" values
    # Ref: https://msdn.microsoft.com/en-us/library/aa367017(v=vs.85).aspx
    $RangedMember = 'member;range={0}-{1}' -f $Start,$($Start + $Range - 1)
    $GroupSearcher.PropertiesToLoad.Add($RangedMember) | Out-Null

    # Retrieve group        
    $Group = $GroupSearcher.FindOne()

    # return on failure
    if(-not $Group) {
      Write-Error -Message ('Group "{0}" not found' -f $GroupName)
      return $false
    }

    # If we've reached the end of the member list, 
    # AD will return a property where the upper range
    # value is *, so it might not be the same property 
    # name we specified in PropertiesToLoad
    $ReturnedMember = @($Group.Properties.PropertyNames) -like 'member;*'

    # Add all members to the $GroupMembers variable
    foreach($member in $Group.Properties."$ReturnedMember") { 
      # Test if user is in the member list
      if($member -eq $User.DistinguishedName){
        return $true
      }
    }

    # If we've reached the end, exit the loop
    if($ReturnedMember -eq $RangedPropertyName){
      $HasMoreMembers = $true
    }

  } while ($HasMoreMembers)

  # User wasn't found
  return $false
}

为了在用户体验上提供一点一致性,请在 PowerShell 中使用 Approved Verbs 作为命令名称(例如 Test-* 而不是 Check-*

[adsisearcher]DirectorySearcher class

的类型加速器