使用Get-AzureADAuditSignInLogs遇1000条限制及429错误的解决方案问询
AzureADPreview模块Get-AzureADAuditSignInLogs触发429限流的规避方案
核心适配方案(完全基于AzureADPreview模块实现,无需调用原生HTTP接口)
- 方案1:添加429错误捕获与指数退避重试逻辑
直接在调用Get-AzureADAuditSignInLogs的逻辑外层套错误捕获,识别到429错误后按递增时长等待后重试,设置最大重试次数避免死循环即可。 - 方案2:主动控制请求频率
每处理完少量用户就添加固定等待时长,避免短时间内请求量突增触发阈值;同时可将多个用户的UPN合并到同一条Filter语句中,用or拼接,大幅减少总请求次数。 - 方案3:拆分时间查询范围
原有30天的查询范围可拆分为按天查询,单次请求返回的数据量更小,同时也能降低单请求的处理负载,进一步减少限流触发概率。
优化后可直接使用的代码
Write-Output ("--- Get All AAD SignOns ---") $filterDate = "{0:yyyy-MM-dd}" -f (get-date).AddDays(-30) $TempFileName = $TempDir + $storageblobpath + $FileName + "AADSignOn.csv" $usrCount = 0 $logCount = 0 # 重试配置 $maxRetryCount = 5 $baseWaitSeconds = 2 ForEach ($user in $users) { $usrCount++ $retryCount = 0 $success = $false while (-not $success -and $retryCount -lt $maxRetryCount) { try { $signons = Get-AzureADAuditSignInLogs -Filter "createdDateTime ge $filterDate and userPrincipalName eq '$user.UserPrincipalName'" -ErrorAction Stop | Select-Object Id,CreatedDateTime,UserId,AppId,AppDisplayName,IpAddress,ClientAppUsed,IsInteractive,TokenIssuerType,ProcessingTimeInMilliseconds, @{name='DeviceId';expression={$_.DeviceDetail.DeviceId} }, @{name='DeviceDisplayName';expression={$_.DeviceDetail.DisplayName} }, @{name='DeviceOperatingSystem';expression={$_.DeviceDetail.OperatingSystem} }, @{name='DeviceBrowser';expression={$_.DeviceDetail.Browser} }, @{name='DeviceIsCompliant';expression={$_.DeviceDetail.IsCompliant} }, @{name='DeviceIsManaged';expression={$_.DeviceDetail.IsManaged} }, @{name='DeviceTrustType';expression={$_.DeviceDetail.TrustType} }, @{name='LocationCity';expression={$_.Location.City} }, @{name='LocationState';expression={$_.Location.State} }, @{name='LocationCountryOrRegion';expression={$_.Location.CountryOrRegion} } $signons | Export-Csv -Path $TempFileName -NoTypeInformation -Append $logCount += $signons.Count $success = $true # 每请求1次加1秒基础延迟,可根据实际情况调整 Start-Sleep -Seconds 1 } catch { if ($_.Exception.Message -match "Too Many Requests" -or $_.Exception.HttpStatusCode -eq 429) { $retryCount++ $waitSeconds = $baseWaitSeconds * [math]::Pow(2, $retryCount) Write-Output "触发429限流,等待$waitSeconds 秒后进行第 $retryCount 次重试" Start-Sleep -Seconds $waitSeconds } else { # 非限流错误直接抛出 throw $_ } } } if ($usrCount % 200 -eq 0) { Write-Output ("Users {0}, {1} Logs so far" -f $usrCount, $logCount) # 每处理200个用户额外多等待10秒,进一步缓解限流压力 Start-Sleep -Seconds 10 } }
额外优化建议
如果你的租户用户量很大,还可以调整Filter的拼接逻辑,每次同时查询5-10个用户的登录日志,示例Filter格式如下:"createdDateTime ge $filterDate and (userPrincipalName eq 'user1@domain.com' or userPrincipalName eq 'user2@domain.com' ...)"
该调整可将总请求量降低数倍,从根源上减少限流触发概率。
内容的提问来源于stack exchange,提问作者Harry Leboeuf
相关产品推荐
相关产品推荐

