为何-contains无法匹配AD安全权限PSCustomObjects?求解决方案
解决AD职位权限分组统计问题
核心问题分析
- 对象引用匹配失效:
Get-ADPrincipalGroupMembership返回的是AD组对象实例,PowerShell的-contains运算符比较对象时,校验的是对象的内存引用而非属性值。即使两个组名称完全相同,只要是不同的对象实例,-contains就会返回false。 - 统计逻辑缺陷:原代码仅通过"首次加入异常列表、二次加入共享列表"的方式判断共享权限,无法处理3个及以上用户的场景,也无法准确反映权限在用户群体中的真实覆盖情况。
- 字符串提取不彻底:使用
Select Name会返回带有Name属性的自定义对象,而非纯字符串,直接用-contains比较仍会触发对象引用匹配问题。
修正后的实现代码
# 获取所有非空职位的AD用户并按职位分组 $titleGroups = Get-ADUser -Filter * -Properties Title | Where-Object { $_.Title.Trim() -ne '' } | Group-Object Title # 遍历每个职位分组 foreach ($group in $titleGroups) { $title = $group.Name $totalUsers = $group.Count $permissionFrequency = @{} # 统计该职位下所有用户的AD组出现次数 foreach ($user in $group.Group) { # 提取当前用户的所有AD组名称(纯字符串) $userGroups = Get-ADPrincipalGroupMembership $user | Select-Object -ExpandProperty Name foreach ($groupName in $userGroups) { # 更新哈希表中的计数 $permissionFrequency[$groupName] = ($permissionFrequency[$groupName] ?? 0) + 1 } } # 筛选共享权限(所有用户都拥有的组) $sharedPermissions = $permissionFrequency.GetEnumerator() | Where-Object { $_.Value -eq $totalUsers } | Sort-Object Name | Select-Object -ExpandProperty Name # 筛选异常权限(仅部分用户拥有的组) $outlierPermissions = $permissionFrequency.GetEnumerator() | Where-Object { $_.Value -lt $totalUsers } | Sort-Object Name | Select-Object -ExpandProperty Name # 输出结果(可替换为导出到CSV/JSON等操作) Write-Host "=== 职位: $title (用户总数: $totalUsers) ===" Write-Host "共享权限:" $sharedPermissions | ForEach-Object { Write-Host " - $_" } Write-Host "异常权限:" $outlierPermissions | ForEach-Object { Write-Host " - $_" } Write-Host "`n" }
关键优化点
- 哈希表统计频率:用
$permissionFrequency哈希表记录每个组名称的出现次数,彻底规避对象引用匹配的问题。 - 纯字符串提取:通过
Select-Object -ExpandProperty Name直接获取组名称的纯字符串值,确保统计的是文本内容而非对象。 - 基于用户总数判断:
- 共享权限:组的出现次数等于该职位的用户总数(所有用户都加入了该组)
- 异常权限:组的出现次数小于用户总数(仅部分用户拥有该权限)
- 空职位过滤:通过
Where-Object { $_.Title.Trim() -ne '' }过滤掉无职位的用户,避免无效分组。
内容的提问来源于stack exchange,提问作者A B
相关产品推荐
相关产品推荐

