技术问询:通过Graph API从Azure AD获取用户并转为带全属性的C#列表
获取Azure AD所有用户及全部属性的C#实现方案
我来给你整理两个可行的实现方案,一个是用官方推荐的Microsoft Graph SDK(代码更简洁易维护),另一个是直接发送HTTP请求(适合不想依赖SDK的场景),都能满足你获取所有用户及全部属性的需求:
前置准备工作
在写代码之前,你需要先在Azure AD中完成应用注册:
- 登录Azure门户,注册一个应用程序(选择“帐户类型”为“仅限此组织目录中的帐户”)
- 为该应用添加应用权限:搜索并添加
Directory.Read.All权限,然后点击“授予管理员同意”(必须完成这一步,否则无法获取所有用户) - 记录下三个关键信息:租户ID、客户端ID、客户端密钥(在应用的“证书和密码”页面生成)
方案一:使用Microsoft Graph SDK(推荐)
这个方案依赖官方SDK,无需手动处理令牌和分页逻辑,代码更简洁。
1. 安装NuGet包
在你的C#项目中安装两个NuGet包:
Install-Package Microsoft.Graph Install-Package Azure.Identity
2. 完整代码示例
using Microsoft.Graph; using Azure.Identity; using System.Collections.Generic; using System.Threading.Tasks; using System; using System.Text.Json; namespace AzureADUserExport { class Program { static async Task Main(string[] args) { // 替换为你的Azure AD信息 string tenantId = "你的租户ID"; string clientId = "你的应用客户端ID"; string clientSecret = "你的应用客户端密钥"; // 创建身份验证凭据 var credential = new ClientSecretCredential(tenantId, clientId, clientSecret); // 初始化Graph服务客户端 var graphClient = new GraphServiceClient(credential); // 存储所有用户的列表 List<User> allUsers = new List<User>(); // 第一次请求用户数据,指定$select=*获取全部属性 var usersPage = await graphClient.Users .Request() .Select("*") // 关键:必须添加这个才能获取所有属性,否则只返回默认属性 .GetAsync(); allUsers.AddRange(usersPage.CurrentPage); // 处理分页:如果用户数量超过100,Graph会分页返回,需要循环获取所有页 while (usersPage.NextPageRequest != null) { usersPage = await usersPage.NextPageRequest.GetAsync(); allUsers.AddRange(usersPage.CurrentPage); } // 转换为JSON并保存到文件 string jsonOutput = JsonSerializer.Serialize(allUsers, new JsonSerializerOptions { WriteIndented = true }); System.IO.File.WriteAllText("AzureAD_AllUsers.json", jsonOutput); // 输出结果统计 Console.WriteLine($"成功导出 {allUsers.Count} 个用户,已保存到AzureAD_AllUsers.json"); } } }
方案二:直接HTTP请求调用Graph API
如果你不想依赖SDK,可以直接通过HttpClient发送请求,手动处理令牌和分页。
完整代码示例
using System; using System.Collections.Generic; using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Text.Json; using System.Threading.Tasks; namespace AzureADUserExportHttp { class Program { static async Task Main(string[] args) { // 替换为你的Azure AD信息 string tenantId = "你的租户ID"; string clientId = "你的应用客户端ID"; string clientSecret = "你的应用客户端密钥"; // 第一步:获取访问令牌 string tokenUrl = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token"; var tokenRequestContent = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("client_id", clientId), new KeyValuePair<string, string>("client_secret", clientSecret), new KeyValuePair<string, string>("grant_type", "client_credentials"), new KeyValuePair<string, string>("scope", "https://graph.microsoft.com/.default") }); using var httpClient = new HttpClient(); var tokenResponse = await httpClient.PostAsync(tokenUrl, tokenRequestContent); tokenResponse.EnsureSuccessStatusCode(); // 确保令牌获取成功 var tokenData = JsonSerializer.Deserialize<TokenResponse>(await tokenResponse.Content.ReadAsStringAsync()); string accessToken = tokenData.access_token; // 第二步:循环获取所有用户(处理分页) httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); List<JsonElement> allUsers = new List<JsonElement>(); string nextRequestUrl = "https://graph.microsoft.com/v1.0/users?$select=*"; while (!string.IsNullOrEmpty(nextRequestUrl)) { var userResponse = await httpClient.GetAsync(nextRequestUrl); userResponse.EnsureSuccessStatusCode(); var userData = JsonSerializer.Deserialize<UserListResponse>(await userResponse.Content.ReadAsStringAsync()); allUsers.AddRange(userData.value); // 更新下一页的请求地址 nextRequestUrl = userData.OdataNextLink; } // 转换为JSON并保存 string jsonOutput = JsonSerializer.Serialize(allUsers, new JsonSerializerOptions { WriteIndented = true }); System.IO.File.WriteAllText("AzureAD_AllUsers_Http.json", jsonOutput); Console.WriteLine($"成功导出 {allUsers.Count} 个用户,已保存到AzureAD_AllUsers_Http.json"); } // 用于反序列化令牌响应的模型类 private class TokenResponse { public string access_token { get; set; } public string token_type { get; set; } } // 用于反序列化用户列表响应的模型类 private class UserListResponse { public List<JsonElement> value { get; set; } [JsonPropertyName("@odata.nextLink")] public string OdataNextLink { get; set; } } } }
关键注意事项
- 权限必须正确配置:一定要给应用添加
Directory.Read.All的应用权限并完成管理员同意,否则会返回权限不足的错误 - 必须指定$select=*:Graph API默认只返回约20个常用属性,只有添加
$select=*才能获取用户的全部属性 - 处理分页:当组织内用户超过100个时,Graph API会分页返回结果,必须通过
@odata.nextLink循环获取所有页的数据 - 敏感属性:部分敏感属性(如
userPrincipalName之外的身份信息)可能需要额外的权限,如果遇到属性缺失,可以检查Azure AD的权限配置
内容的提问来源于stack exchange,提问作者JhonBlack
相关产品推荐
相关产品推荐

