You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure DevOps API获取AAD组成员返回数量不全问题咨询

问题原因

你遇到的成员拉取不全问题,是接口特性未做对应处理导致的,和用户特殊属性配置无关:

  • 你当前使用的6.1-preview版本接口默认分页返回结果,单页不会返回全量直接成员,且该预览版本对分页令牌的处理存在已知bug,很容易漏返回结果
  • 该接口默认仅返回目标组下的直接成员,不会自动递归展开嵌套在组内的子AAD组/DevOps组。你在Azure Portal和DevOps前端看到的成员数,是自动计算了所有嵌套子组成员的总数,仅发一次请求自然拿不到全量数据
  • 额外注意:你贴的请求URL末尾多了一个多余的右括号),实际调用时记得移除,避免触发异常返回。
解决方案

按以下逻辑调整调用方式即可拉取全量成员:

  1. 替换接口版本为7.1正式版,不要使用任何preview版本的Graph接口
  2. 增加分页处理逻辑:每次请求带上$top=100参数拉取单页最大量结果,请求后检查响应头的X-MS-ContinuationToken字段,如果存在值就作为下一次请求的continuationToken参数传入,直到响应头没有该字段时,才拿全了当前组的所有直接成员
  3. 增加嵌套组递归逻辑:遍历拿到的直接成员时,判断成员类型,如果是组类型对象就递归执行分页拉取逻辑,直到所有层级的子组都遍历完成;如果是用户类型对象就收集到结果集中,注意加已处理组的标记,避免循环嵌套组导致死循环
PowerShell参考实现代码
# 配置基础参数
$orgName = "替换为你的Azure DevOps组织名"
$pat = "替换为你的个人访问令牌,需授予Graph读取权限"
$targetGroupDescriptor = "替换为目标AAD组的subjectDescriptor"
$base64Auth = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($pat)"))
$requestHeaders = @{Authorization = "Basic $base64Auth"}
$allMemberUsers = @()
$processedGroupList = @() # 记录已处理的组,避免循环嵌套导致死循环

function Get-AllGroupMembers {
    param([string]$currentGroupDescriptor)
    # 跳过已经处理过的组
    if ($processedGroupList -contains $currentGroupDescriptor) { return }
    $processedGroupList += $currentGroupDescriptor
    $nextPageToken = $null

    do {
        # 拼接请求地址
        $requestUri = "https://vssps.dev.azure.com/$orgName/_apis/graph/Memberships/$currentGroupDescriptor?direction=down&`$top=100&api-version=7.1"
        if ($nextPageToken) { $requestUri += "&continuationToken=$nextPageToken" }
        # 发请求,保留响应头拿分页令牌
        $response = Invoke-WebRequest -Uri $requestUri -Headers $requestHeaders -Method Get
        $pageResult = $response.Content | ConvertFrom-Json

        # 遍历当前页成员
        foreach ($member in $pageResult.value) {
            $memberDsp = $member.memberDescriptor
            # 判断为组类型,递归拉取
            if ($memberDsp -like "aad.gp*" -or $memberDsp -like "vssgp.*") {
                Get-AllGroupMembers -currentGroupDescriptor $memberDsp
            }
            # 判断为用户类型,拉取用户详情加入结果集
            elseif ($memberDsp -like "aad.*" -or $memberDsp -like "usp.*") {
                $userDetailUri = "https://vssps.dev.azure.com/$orgName/_apis/graph/users/$memberDsp?api-version=7.1"
                $userDetail = Invoke-RestMethod -Uri $userDetailUri -Headers $requestHeaders -Method Get
                $allMemberUsers += $userDetail
            }
        }
        # 读取下一页令牌
        $nextPageToken = $response.Headers.'X-MS-ContinuationToken'
    } while ($nextPageToken)
}

# 执行拉取
Get-AllGroupMembers -currentGroupDescriptor $targetGroupDescriptor
# 导出为CSV文件,可按需调整要导出的字段
$allMemberUsers | Select-Object displayName, mailAddress, principalName, originId | Export-Csv -Path "AAD组全量成员.csv" -NoTypeInformation -Encoding UTF8
注意事项
  • 个人访问令牌需要授予组织范围的Graph读取权限,不要用项目范围的令牌,否则会漏读未分配到对应项目的用户
  • 如果组织开启了用户可见性限制策略,需要确认调用接口所用的身份有查看全组织用户的权限,否则只会返回权限范围内的可见用户

内容的提问来源于stack exchange,提问作者user19364865

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 08:39:10