Windows AD PowerShell(二):组与成员
这是 Windows AD PowerShell 学习记录的第二节,主要整理组对象、成员关系、嵌套组及权限不生效时的排查方法。
二、组与成员
2.1 查询组的基本信息
# 查询所有组Get-ADGroup -Filter *
DistinguishedName : CN=QYNET-Admin,OU=Group,OU=Organization,DC=qy,DC=netGroupCategory : SecurityGroupScope : GlobalName : QYNET-AdminObjectClass : groupSamAccountName : QYNET-Admin
DistinguishedName : CN=Domain Admins,CN=Users,DC=qy,DC=netGroupCategory : SecurityGroupScope : GlobalName : Domain AdminsObjectClass : groupSamAccountName : Domain Admins# 查询单个组Get-ADGroup -Identity "QYNET-Admin"
DistinguishedName : CN=QYNET-Admin,OU=Group,OU=Organization,DC=qy,DC=netGroupCategory : SecurityGroupScope : GlobalName : QYNET-AdminObjectClass : groupSamAccountName : QYNET-Admin# 按名称进行模糊查询Get-ADGroup -Filter 'Name -like "*Admin*"'
Name GroupScope GroupCategory SamAccountName---- ---------- ------------- --------------QYNET-Admin Global Security QYNET-AdminDomain Admins Global Security Domain AdminsDHCP Administrators DomainLocal Security DHCP Administrators# 查询指定 OU 下的组Get-ADGroup ` -SearchBase "OU=Group,OU=Organization,DC=qy,DC=net" ` -Filter *
DistinguishedName : CN=QYNET-Admin,OU=Group,OU=Organization,DC=qy,DC=netGroupCategory : SecurityGroupScope : GlobalName : QYNET-AdminSamAccountName : QYNET-Admin# 只显示常用字段Get-ADGroup -Filter * | Select-Object Name,SamAccountName,GroupScope,GroupCategory,DistinguishedName
Name SamAccountName GroupScope GroupCategory DistinguishedName---- -------------- ---------- ------------- -----------------QYNET-Admin QYNET-Admin Global Security CN=QYNET-Admin,OU=Group,OU=Organization,DC=qy,DC=netDomain Admins Domain Admins Global Security CN=Domain Admins,CN=Users,DC=qy,DC=netDomain Users Domain Users Global Security CN=Domain Users,CN=Users,DC=qy,DC=netGet-ADGroup 默认会返回组的基本属性。如果需要查看描述、成员或创建时间等额外属性,需要通过 -Properties 指定:
Get-ADGroup -Identity "QYNET-Admin" ` -Properties Description,Members,Created,Modified | Select-Object Name,Description,GroupScope,GroupCategory,Created,Modified
Name : QYNET-AdminDescription :GroupScope : GlobalGroupCategory : SecurityCreated : 2026/9/10 10:32:18Modified : 2026/9/20 09:15:42上面的时间仅用于展示输出格式,实际结果以域中的对象属性为准。
常见的组属性如下:
| 属性 | 含义 |
|---|---|
| Name | AD 组对象的名称 |
| SamAccountName | 组的旧式 Windows 名称 |
| DistinguishedName | 组对象在 AD 中的完整路径 |
| GroupScope | 组的作用域,例如 Global、DomainLocal、Universal |
| GroupCategory | 组的类型,例如 Security 或 Distribution |
| Members | 组的直接成员 DN 列表 |
| MemberOf | 当前组直接加入了哪些组 |
| Description | 组的用途说明 |
| Created | 组对象的创建时间 |
| Modified | 组对象最后一次修改的时间 |
2.2 理解组作用域与组类型
GroupScope 与 GroupCategory 是权限排查中的高频字段:
| 字段 | 取值 | 可以包含的常见成员 | 可以在哪里授权 |
|---|---|---|---|
| GroupScope | DomainLocal | 任意受信任域中的账户和全局组,以及本林中的通用组 | 仅当前组所在域 |
| GroupScope | Global | 同一域中的账户和全局组 | 本林或受信任域中的资源 |
| GroupScope | Universal | 本林任意域中的账户、全局组和通用组 | 本林或受信任林中的资源 |
| GroupCategory | Security | 安全主体,可以加入 ACL | 可以用于权限分配,也可以用于邮件分发 |
| GroupCategory | Distribution | 仅用于逻辑分组或邮件分发 | 不能用于 ACL 权限分配 |
如果用户已经加入某个组却仍然没有权限,应先检查该组是不是 Distribution 通讯组。通讯组不是安全主体,不参与 ACL 访问判定。
Get-ADGroup -Identity "QYNET-Admin" | Select-Object Name,GroupScope,GroupCategory
Name GroupScope GroupCategory---- ---------- -------------QYNET-Admin Global Security在多域环境中,通常使用 AGDLP 或 AGUDLP 模型规划权限:
AGDLP :账户(A)→ 全局组(G)→ 域本地组(DL)→ 权限(P)AGUDLP :账户(A)→ 全局组(G)→ 通用组(U)→ 域本地组(DL)→ 权限(P)这种方式可以把“人员归属”和“资源权限”分开管理,减少直接向用户账户分配权限的情况。
2.3 创建、修改与删除组
创建一个全局安全组:
New-ADGroup ` -Name "GG-IT-Admins" ` -SamAccountName "GG-IT-Admins" ` -GroupScope Global ` -GroupCategory Security ` -Path "OU=Group,OU=Organization,DC=qy,DC=net" ` -Description "IT 管理员账户组"执行成功时默认不返回内容,可以立即查询验证:
Get-ADGroup -Identity "GG-IT-Admins"
DistinguishedName : CN=GG-IT-Admins,OU=Group,OU=Organization,DC=qy,DC=netGroupCategory : SecurityGroupScope : GlobalName : GG-IT-AdminsObjectClass : groupSamAccountName : GG-IT-Admins修改组的描述信息:
Set-ADGroup ` -Identity "GG-IT-Admins" ` -Description "用于管理 IT 系统的安全组"执行成功时默认不返回内容,验证结果如下:
Get-ADGroup -Identity "GG-IT-Admins" -Properties Description | Select-Object Name,Description
Name Description---- -----------GG-IT-Admins 用于管理 IT 系统的安全组修改组对象的名称:
Get-ADGroup -Identity "GG-IT-Admins" | Rename-ADObject -NewName "GG-System-Admins"执行成功时默认不返回内容。再次查询时,CN 已经发生变化:
Get-ADGroup -Identity "GG-IT-Admins" | Select-Object Name,SamAccountName,DistinguishedName
Name SamAccountName DistinguishedName---- -------------- -----------------GG-System-Admins GG-IT-Admins CN=GG-System-Admins,OU=Group,OU=Organization,DC=qy,DC=netRename-ADObject 修改的是对象的 CN;如果还需要修改 SamAccountName,应另外使用 Set-ADGroup:
Set-ADGroup -Identity "GG-System-Admins" -SamAccountName "GG-System-Admins"执行成功时默认不返回内容。可使用以下命令同时验证 CN 与 SamAccountName:
Get-ADGroup -Identity "GG-System-Admins" | Select-Object Name,SamAccountName
Name SamAccountName---- --------------GG-System-Admins GG-System-Admins删除组属于高风险操作,建议先使用 -WhatIf 确认目标:
Remove-ADGroup -Identity "GG-System-Admins" -WhatIf
What if: Performing the operation "Remove" on target "CN=GG-System-Admins,OU=Group,OU=Organization,DC=qy,DC=net".# 确认无误后再执行,并保留确认提示Remove-ADGroup -Identity "GG-System-Admins" -Confirm
ConfirmAre you sure you want to perform this action?[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help: Y
# 输入 Y 后执行删除,成功时不会再返回对象2.4 查询组成员
Get-ADGroupMember 默认只返回组的直接成员:
# 查询组的直接成员Get-ADGroupMember -Identity "QYNET-Admin"
distinguishedName : CN=浅月,OU=User,OU=Admin,OU=Organization,DC=qy,DC=netname : 浅月objectClass : userSamAccountName : qianyue# 整理常用字段Get-ADGroupMember -Identity "QYNET-Admin" | Select-Object Name,SamAccountName,ObjectClass,DistinguishedName
Name SamAccountName ObjectClass DistinguishedName---- -------------- ----------- -----------------浅月 qianyue user CN=浅月,OU=User,OU=Admin,OU=Organization,DC=qy,DC=net# 只查询直接成员中的用户对象Get-ADGroupMember -Identity "QYNET-Admin" | Where-Object ObjectClass -eq "user"
distinguishedName : CN=浅月,OU=User,OU=Admin,OU=Organization,DC=qy,DC=netname : 浅月objectClass : userSamAccountName : qianyue如果组中包含嵌套组,可以使用 -Recursive 继续展开:
Get-ADGroupMember -Identity "QYNET-Admin" -Recursive | Select-Object Name,SamAccountName,ObjectClass
Name SamAccountName ObjectClass---- -------------- -----------浅月 qianyue user需要注意,-Recursive 返回的是递归展开后的末端成员,不适合用来还原完整的嵌套层级。如果需要检查“哪个组嵌套了哪个组”,仍应先查看直接成员,并逐层查询其中的组对象。
统计组中递归展开后的用户数量:
$members = Get-ADGroupMember -Identity "QYNET-Admin" -Recursive
$members | Where-Object ObjectClass -eq "user" | Measure-Object
Count : 1Average :Sum :Maximum :Minimum :Property :2.5 查询用户属于哪些组
使用 Get-ADPrincipalGroupMembership 查询用户的组成员关系:
Get-ADPrincipalGroupMembership -Identity qianyue | Select-Object Name,GroupScope,GroupCategory,DistinguishedName
Name GroupScope GroupCategory DistinguishedName---- ---------- ------------- -----------------Domain Users Global Security CN=Domain Users,CN=Users,DC=qy,DC=netQYNET-Admin Global Security CN=QYNET-Admin,OU=Group,OU=Organization,DC=qy,DC=net只查看安全组:
Get-ADPrincipalGroupMembership -Identity qianyue | Where-Object GroupCategory -eq "Security" | Select-Object Name,GroupScope
Name GroupScope---- ----------Domain Users GlobalQYNET-Admin Global如果只想查看用户对象 memberOf 属性中记录的直接组成员关系,可以使用:
(Get-ADUser -Identity qianyue -Properties MemberOf).MemberOf | ForEach-Object { Get-ADGroup -Identity $_ } | Select-Object Name,GroupScope,GroupCategory
Name GroupScope GroupCategory---- ---------- -------------QYNET-Admin Global SecuritymemberOf 只记录直接成员关系,而且通常不包含用户的主组,例如默认的 Domain Users。排查有效组成员关系时,更适合使用 Get-ADPrincipalGroupMembership,并结合登录会话中的访问令牌进行确认。
2.6 添加与移除组成员
# 将单个用户加入组Add-ADGroupMember -Identity "GG-IT-Admins" -Members qianyue# 执行成功时默认无输出
# 一次加入多个用户Add-ADGroupMember ` -Identity "GG-IT-Admins" ` -Members user01,user02,user03# 执行成功时默认无输出
# 将另一个组作为成员加入,实现组嵌套Add-ADGroupMember ` -Identity "DL-Server-Admins" ` -Members "GG-IT-Admins"# 执行成功时默认无输出
# 从组中移除用户,并显示确认提示Remove-ADGroupMember ` -Identity "GG-IT-Admins" ` -Members qianyue ` -Confirm
ConfirmAre you sure you want to perform this action?[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help: Y
# 输入 Y 并成功移除后,默认无输出输入 Y 并成功移除后,同样不会返回对象。是否没有输出不能单独作为变更成功的证明,应继续运行查询命令验证。
添加完成后应再次查询确认,避免因为名称相似而操作了错误的对象:
Get-ADGroupMember -Identity "GG-IT-Admins" | Where-Object SamAccountName -eq "qianyue"
distinguishedName : CN=浅月,OU=User,OU=Admin,OU=Organization,DC=qy,DC=netname : 浅月objectClass : userSamAccountName : qianyue
# 如果已经移除,则不会返回任何内容对高权限组执行成员变更前,可以先解析用户和组的完整 DN:
Get-ADUser -Identity qianyue | Select-Object Name,SamAccountName,DistinguishedName
Get-ADGroup -Identity "GG-IT-Admins" | Select-Object Name,SamAccountName,DistinguishedName
Name SamAccountName DistinguishedName---- -------------- -----------------浅月 qianyue CN=浅月,OU=User,OU=Admin,OU=Organization,DC=qy,DC=net
Name SamAccountName DistinguishedName---- -------------- -----------------GG-IT-Admins GG-IT-Admins CN=GG-IT-Admins,OU=Group,OU=Organization,DC=qy,DC=net2.7 查询空组与统计成员数量
查询没有任何直接成员的组:
Get-ADGroup -Filter * -Properties Members | Where-Object { -not $_.Members } | Select-Object Name,GroupScope,GroupCategory,DistinguishedName
Name GroupScope GroupCategory DistinguishedName---- ---------- ------------- -----------------WSUS Reporters DomainLocal Security CN=WSUS Reporters,CN=Users,DC=qy,DC=netWSUS Administrators DomainLocal Security CN=WSUS Administrators,CN=Users,DC=qy,DC=netDHCP Users DomainLocal Security CN=DHCP Users,CN=Users,DC=qy,DC=net查询每个组的直接成员数量:
Get-ADGroup -Filter * -Properties Members | Select-Object Name,GroupScope,GroupCategory, @{Name="DirectMemberCount";Expression={ @($_.Members).Count }} | Sort-Object DirectMemberCount -Descending
Name GroupScope GroupCategory DirectMemberCount---- ---------- ------------- -----------------Exchange Servers Universal Security 2QYNET-Admin Global Security 1Organization Management Universal Security 1WSUS Reporters DomainLocal Security 0需要注意,Members 属性和上面的统计结果只包含直接成员,不会自动计算嵌套组中的用户。如果对所有组逐一执行递归查询,会对域控制器产生更多查询压力,生产环境中应尽量限制 OU 和组的范围。
2.8 转换组作用域与类型
使用 Set-ADGroup 可以修改组作用域:
# 将全局组转换为通用组Set-ADGroup -Identity "GG-IT-Admins" -GroupScope Universal
# 修改组类型Set-ADGroup -Identity "Mail-IT" -GroupCategory Security两条命令执行成功时默认不返回内容,可以分别查询验证:
Get-ADGroup -Identity "GG-IT-Admins" | Select-Object Name,GroupScope,GroupCategory
Get-ADGroup -Identity "Mail-IT" | Select-Object Name,GroupScope,GroupCategory
Name GroupScope GroupCategory---- ---------- -------------GG-IT-Admins Universal Security
Name GroupScope GroupCategory---- ---------- -------------Mail-IT Universal Security组作用域不能任意转换,常见约束如下:
| 转换方向 | 主要约束 |
|---|---|
| Global → Universal | 当前全局组不能是另一个全局组的成员 |
| DomainLocal → Universal | 当前域本地组不能包含其他域本地组,并且成员必须符合通用组的成员规则 |
| Universal → Global | 成员必须符合全局组规则,即只能包含本域账户和本域全局组,不能包含通用组 |
| Universal → DomainLocal | 当前通用组不能处于不允许转换的通用组或跨域域本地组嵌套关系中 |
| Global ↔ DomainLocal | 不能直接互转,需要先转换成 Universal,再转换为目标作用域 |
早期的 Windows 2000 Mixed 模式不支持 Universal 安全组,也不允许组作用域转换;这不是“林功能级别低于 2003”的限制。现代 AD 环境通常不会再使用该模式,但转换前仍然必须检查成员和嵌套关系。
组类型从 Distribution 改成 Security 后可能立即影响权限判定;从 Security 改成 Distribution 后,ACL 中引用该组的授权将不再生效,因此修改前应先检查使用范围。
2.9 导出组及成员信息
执行导出前需要确保 C:\Temp 已经存在:
New-Item -Path "C:\Temp" -ItemType Directory -Force
Directory: C:\
Mode LastWriteTime Length Name---- ------------- ------ ----d---- 2026/9/20 14:30 Temp如果目录已经存在,-Force 会直接返回现有目录。
将组的基本信息导出为 CSV:
Get-ADGroup -Filter * | Select-Object Name,SamAccountName,GroupScope,GroupCategory,DistinguishedName | Export-Csv -Path "C:\Temp\AD-Groups.csv" -NoTypeInformation -Encoding UTF8Export-Csv 成功时默认不返回内容,可以使用 Get-Item 验证文件:
Get-Item -Path "C:\Temp\AD-Groups.csv" | Select-Object Name,Length,LastWriteTime
Name Length LastWriteTime---- ------ -------------AD-Groups.csv 18264 2026/9/20 14:31:05导出指定组递归展开后的成员:
Get-ADGroupMember -Identity "QYNET-Admin" -Recursive | Select-Object Name,SamAccountName,ObjectClass,DistinguishedName | Export-Csv -Path "C:\Temp\QYNET-Admin-Members.csv" -NoTypeInformation -Encoding UTF8同样地,成功时不会在控制台输出对象,可以导入文件检查内容:
Import-Csv -Path "C:\Temp\QYNET-Admin-Members.csv"
Name SamAccountName ObjectClass DistinguishedName---- -------------- ----------- -----------------浅月 qianyue user CN=浅月,OU=User,OU=Admin,OU=Organization,DC=qy,DC=net2.10 “已经加入组但仍然没有权限”的排查流程
当用户已经加入组但仍然无法访问资源时,可以按照以下顺序排查:
- 检查目标组的
GroupCategory是否为Security。 - 检查用户是否是该组的直接成员或递归成员。
- 检查嵌套组的作用域和成员规则是否合法。
- 检查用户当前登录令牌中是否已经包含该组。
- 检查资源 ACL 是否真正向该组授予了权限。
- 检查是否存在优先级更高的显式拒绝权限。
- 检查域控制器复制是否已经完成。
首先检查组本身:
Get-ADGroup -Identity "QYNET-Admin" | Select-Object Name,GroupScope,GroupCategory,DistinguishedName
Name GroupScope GroupCategory DistinguishedName---- ---------- ------------- -----------------QYNET-Admin Global Security CN=QYNET-Admin,OU=Group,OU=Organization,DC=qy,DC=net然后检查用户是否位于递归成员列表中:
Get-ADGroupMember -Identity "QYNET-Admin" -Recursive | Where-Object SamAccountName -eq "qianyue"
distinguishedName : CN=浅月,OU=User,OU=Admin,OU=Organization,DC=qy,DC=netname : 浅月objectClass : userSamAccountName : qianyue在用户实际登录的计算机上检查当前访问令牌:
whoami /groups
GROUP INFORMATION-----------------
Group Name Type SID Attributes====================== ================ ============================================= ==================================================QYNET\QYNET-Admin Group S-1-5-21-... Mandatory group, Enabled by default, Enabled groupQYNET\Domain Users Group S-1-5-21-...-513 Mandatory group, Enabled by default, Enabled group组成员关系发生变化后,已经存在的登录会话不会自动获得新的访问令牌。最可靠的验证方式是让用户注销并重新登录;某些 Kerberos 场景也可以执行 klist purge 后重新访问资源,但现有 SMB 会话等连接仍可能继续使用旧状态。
检查文件或目录 ACL:
Get-Acl -Path "\\server\share\folder" | Select-Object -ExpandProperty Access | Where-Object IdentityReference -like "*GG-IT-Admins*"
FileSystemRights : Modify, SynchronizeAccessControlType : AllowIdentityReference : QYNET\GG-IT-AdminsIsInherited : TrueInheritanceFlags : ContainerInherit, ObjectInheritPropagationFlags : None最后检查 AD 复制状态:
repadmin /replsummary
Source DSA largest delta fails/total %% errorDC01 05m:12s 0 / 5 0
Destination DSA largest delta fails/total %% errorDC01 05m:12s 0 / 5 0如果不同命令连接到了不同域控制器,也可以使用 -Server 指定同一台 DC 进行对比:
Get-ADGroupMember ` -Identity "QYNET-Admin" ` -Recursive ` -Server "QYNET-CORE01.qy.net"
distinguishedName : CN=浅月,OU=User,OU=Admin,OU=Organization,DC=qy,DC=netname : 浅月objectClass : userSamAccountName : qianyue排查权限问题时,需要同时区分三件事:AD 中保存的组成员关系、用户登录时生成的访问令牌,以及目标资源上的实际 ACL。只确认其中一项,并不能证明权限已经完整生效。
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!













