2

我需要按照一些业务规则从 ASP.NET Core 2 应用程序向用户发送电子邮件。但是,我需要确保发送电子邮件的帐户确实存在(由于某种原因,该帐户可能不再有效)。客户正在使用 Azure Active Directory,因此我需要以某种方式查询 AAD,以便让我知道该帐户是否存在。

到目前为止,我一直在寻找 Microsoft Graph 作为执行此操作的一种方式,但是到目前为止我看到的每个示例都需要事先身份验证并使用委托身份验证机制。我不希望我的用户必须进行身份验证,也不想提示身份验证屏幕。

鉴于这种情况,您建议使用什么?如果你也可以给我举个例子,那就太好了。谢谢!

4

4 回答 4

2

您实际上不需要像在当前代码中那样为每个无效用户抛出/捕获异常。由于其他原因,我一般不反对异常处理,但要查看用户是否存在,您可以尝试使用Filter.

所以你的图形查询可能看起来像 -

https://graph.microsoft.com/v1.0/users?$filter=startswith(userPrincipalName,'someuser@mytenant.onmicrosoft.com')

我在startswith这里展示了,因为eq在快速试用中对我不起作用。虽然我会推荐两件事:

这是您的代码的修改版本。

请注意,我正在检查集合计数是否大于 0,而不是检查它是否为空,因为即使在未找到用户的情况下,我的测试运行的 UsersCollectionPage 也不为空。

using Microsoft.Identity.Client;
using Microsoft.Graph.Auth;
using Microsoft.Graph;
...

private async Task<bool> ValidateAccounts(string accounts) {
    var confidentialClientApplication = ConfidentialClientApplicationBuilder
        .Create("clientId here")
        .WithTenantId("tokenId here")
        .WithClientSecret("secret here")
        .Build();
    var authProvider = new ClientCredentialProvider(confidentialClientApplication);
    var graphClient = new GraphServiceClient(authProvider);

    var valid = true;
    try {
        foreach (var account in accounts.Split(';')) {
            var user = await graphClient.Users.Request().Filter("startswith(userPrincipalName, '" + account + "')").GetAsync();

            if (user.Count <= 0) {
                valid = false;
                break;
            }
        }
    } catch (ServiceException ex) {
        valid = false;
    }

    return valid;
}

附带说明一下,我不确定您的要求,但您可以通过在单个查询中组合多个用户名然后检查结果计数或其他属性来获得创意。您可以or在多个条件之间使用或可能使用any运算符。不过,我还没有真正尝试过。

于 2019-10-14T22:52:56.173 回答
1

最后我想出了一些可行的方法。这不好,它使用预览软件。首先,安装 Microsoft.Graph 和 Microsoft.Identity.Client 包。然后安装 Microsoft.Graph.Auth,在撰写本文时,它处于预览状态(v1.0.0-preview.1),因此您需要在 nuget 管理器中勾选“包含预发布”复选框。

然后在您的 AAD 中,您需要获取 ClientId、TenantId 和 SecretId。就我而言,我的应用程序已经在使用 AAD 身份验证,因此我的 appsettings.json 文件中已经有了 ClientId 和 TenantId。我只需要创建一个新的 SecretId(在我的应用注册的证书和机密部分)。然后我需要添加权限(在我的应用注册的 API 权限部分)以包含 Microsoft.Graph 至少具有 User.Read.All 权限。

using Microsoft.Identity.Client;
using Microsoft.Graph.Auth;
using Microsoft.Graph;
...

private async Task<bool> ValidateAccounts(string accounts) {
    var confidentialClientApplication = ConfidentialClientApplicationBuilder
        .Create("clientId here")
        .WithTenantId("tokenId here")
        .WithClientSecret("secret here")
        .Build();
    var authProvider = new ClientCredentialProvider(confidentialClientApplication);
    var graphClient = new GraphServiceClient(authProvider);

    var valid = true;
    try {
        foreach (var account in accounts.Split(';')) {
            var user = await graphClient.Users[account]
                .Request()
                .GetAsync();
            if (user == null) {
                valid = false;
                break;
            }
        }
    } catch (ServiceException ex) {
        valid = false;
    }

    return valid;
}

在这里,该函数为每个帐户采用分号分隔的字符串。如果用户不存在,GetAsync 方法将引发 ServiceException。我不喜欢这样,但找不到其他方法。就是这样。希望这对其他人有所帮助,并希望有人最终能提出更好的解决方案。

于 2019-10-14T19:15:20.877 回答
1

导入以下命名空间(需要使用 nuget 安装相关包):

using Microsoft.Graph;
using Microsoft.IdentityModel.Clients.ActiveDirectory;

设置 Azure AD 应用值:

private string _tenant => "your_tenant_id";
private string _appId => "your_ad_app_client_id";
private string _appSecret => "your_app_client_secret";

使用此创建图形服务客户端:

public static GraphServiceClient CreateGraphServiceClient()
{
  var clientCredential = new ClientCredential(_appId, _appSecret);
  var authenticationContext = new AuthenticationContext("https://login.microsoftonline.com/{_tenant}");
  var authenticationResult = authenticationContext.AcquireTokenAsync("https://graph.microsoft.com", clientCredential).Result;

  var delegateAuthProvider = new DelegateAuthenticationProvider((requestMessage) =>
  {
    requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", authenticationResult.AccessToken);

    return Task.FromResult(0);
   });

  return new GraphServiceClient(delegateAuthProvider);
 }


var graphServiceClient = GraphServiceClientHelper.CreateGraphServiceClient();

然后调用graph api并通过电子邮件地址过滤用户,如下所示:

var user = await graphServiceClient.Users.Request().Filter("mail eq '" + UserEmailAddress + "'").GetAsync();
if (user.Count == 0) {
    //user not exist
}
于 2020-08-12T12:43:48.133 回答
0

下面的代码对我有用。

using Microsoft.Graph;
using Microsoft.Graph.Auth;
using Microsoft.Identity.Client;


private static async Task<bool> ValidateAccounts(string accounts)
{
        var confidentialClientApplication = ConfidentialClientApplicationBuilder
            .Create("client id")
            .WithTenantId("tenant id")
            .WithClientSecret("client secret")
            .Build();

        var authProvider = new ClientCredentialProvider(confidentialClientApplication);
        var graphClient = new GraphServiceClient(authProvider);

        var valid = true;
        try
        {
            foreach (var account in accounts.Split(';'))
            {
            var user = await 
graphClient.Users.Request().Filter($"identities/any(c:c/issuerAssignedId eq 
'{account}' and c/issuer eq 'xyz.onmicrosoft.com')").GetAsync();
            
                if (user.Count <= 0)
                {
                    valid = false;
                    break;
                }
            }
        }
        catch(Exception ex)
        {
            valid = false;
        }
        return valid;
    }
于 2021-03-01T10:34:57.860 回答