1

我正在尝试用 C# 制作一个控制台应用程序,我想通过它将超过 100000 个用户迁移到 Azure AD B2C。

为此,我们使用 Graph API。

我目前的方法是为每个 API 调用创建一个用户帐户,迁移大约 50000 个用户需要 12 多个小时。

为了减少总时间,我想使用 API批量发送数据,而不是一一发送。但是,我无法找到任何解决方案。

是否有 API 端点可用于批量创建用户。请帮忙。

另外,如果我想批量删除这些用户。有可能这样做吗?

以下是我用于实现我的解决方案的一些 Microsoft 文档参考。

https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-user-migration?tabs=applications https://docs.microsoft.com/en-us/previous -versions/azure/ad/graph/api/users-operations#CreateLocalAccountUser

4

3 回答 3

2

您可以使用JSON 批处理在一个 HTTP 调用中组合多个请求。

这是一个例子:

POST https://graph.microsoft.com/v1.0/$batch

{
    "requests": [{
            "id": "1",
            "method": "POST",
            "url": "/users",
            "body": {
                "accountEnabled": true,
                "displayName": "allentest01",
                "mailNickname": "allentest01",
                "userPrincipalName": "allentest01@{tenant}.onmicrosoft.com",
                "passwordProfile": {
                    "forceChangePasswordNextSignIn": true,
                    "password": "{password-value}"
                }
            },
            "headers": {
                "Content-Type": "application/json"
            }
        }, {
            "id": "2",
            "method": "POST",
            "url": "/users",
            "body": {
                "accountEnabled": true,
                "displayName": "allentest02",
                "mailNickname": "allentest02",
                "userPrincipalName": "allentest02@{tenant}.onmicrosoft.com",
                "passwordProfile": {
                    "forceChangePasswordNextSignIn": true,
                    "password": "{password-value}"
                }
            },
            "headers": {
                "Content-Type": "application/json"
            }
        }
    ]
}

您也可以使用它删除用户。(使用DELETE方法)

于 2019-11-22T06:59:03.517 回答
1

只是为了添加到 Allen Wu 的答案。例如,这就是您在 c# 中使用它的方式。

string json = @"
{
    ""requests"": [{
            ""id"": ""1"",
            ""method"": ""POST"",
            ""url"": ""/users"",
            ""body"": {
                ""accountEnabled"": true,
                ""displayName"": ""zetawarsTest01"",
                ""mailNickname"": ""zetawarstest01"",
                ""userPrincipalName"": ""zetawarstest01@projecttarget.onmicrosoft.com"",
                ""passwordProfile"": {
                    ""forceChangePasswordNextSignIn"": false,
                    ""password"": ""zetawars123!@#""
                }
            },
            ""headers"": {
                ""Content-Type"": ""application/json""
            }
        }, {
            ""id"": ""2"",
            ""method"": ""POST"",
            ""url"": ""/users"",
            ""body"": {
                ""accountEnabled"": true,
                ""displayName"": ""zetawarsTest02"",
                ""mailNickname"": ""zetawarsTest02"",
                ""userPrincipalName"": ""zetawarsTest02@projecttarget.onmicrosoft.com"",
                ""passwordProfile"": {
                    ""forceChangePasswordNextSignIn"": false,
                    ""password"": ""zetawars123!@#""
                }
            },
            ""headers"": {
                ""Content-Type"": ""application/json""
            }
        }
        ]
    }
";
            //Credentials
            var tenantId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
            var clientId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
            var clientSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

            var scopes = new string[] { "https://graph.microsoft.com/.default" };

            //This to get the Access Token
            var confidentialClient = ConfidentialClientApplicationBuilder
                .Create(clientId)
                .WithAuthority($"https://login.microsoftonline.com/{tenantId}/v2.0")
                .WithClientSecret(clientSecret)
                .Build();

            IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
                .Create(clientId)
                .WithTenantId(tenantId)
                .WithClientSecret(clientSecret)
                .Build();

            var result = await confidentialClientApplication
                .AcquireTokenForClient(new string[] { "https://graph.microsoft.com/.default" })
                .ExecuteAsync(); ;

             // This is to send Json Request using Client
            using (HttpClient http = new HttpClient())
            using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://graph.microsoft.com/v1.0/$batch"))
            {

                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);


                if (!string.IsNullOrEmpty(json))
                {
                    request.Content = new StringContent(json, Encoding.UTF8, "application/json");
                }


                using (HttpResponseMessage response = await http.SendAsync(request))
                {
                    string error = await response.Content.ReadAsStringAsync();

                    if (!response.IsSuccessStatusCode)
                    {
                        if (response.StatusCode == (HttpStatusCode)429)
                        {
                            // TBD: Add you error handling here
                        }

                        throw new Exception(error);
                    }
                    await response.Content.ReadAsStringAsync();
                }
            }

我已阅读批量限制为 20 个用户/请求。但我还没有测试过。

于 2020-01-16T12:39:21.980 回答
0

使用 JSON 批处理的方法似乎更合理,但上次我们使用 Parallel.ForEach 循环通过 Graph API 将 160,000 个用户导入到 Azure AD B2C,MaxDegreeOfParallelism 为 10。我们每次运行提供一批 40,000 个用户。批量迁移 40,000 个用户用时 30 分钟。

于 2019-11-27T00:57:32.850 回答