教程:以应用的形式从安全的 .NET 应用中访问 Microsoft Graph

了解如何从 Azure 应用服务上运行的 Web 应用访问 Microsoft Graph。

Diagram that shows accessing Microsoft Graph.

你希望为 Web 应用调用 Microsoft Graph。 向 Web 应用授予数据访问权限的安全方法是使用系统分配的托管标识。 Microsoft Entra ID 中的托管标识允许应用服务通过基于角色的访问控制 (RBAC) 访问资源,而不要求使用应用凭据。 向 Web 应用分配托管标识之后,Azure 会负责创建和分发证书。 你无需费心管理机密或应用凭据。

在本教程中,你将了解:

  • 在 Web 应用上创建系统分配的托管标识。
  • 为托管标识添加 Microsoft Graph API 权限。
  • 使用托管标识从 Web 应用调用 Microsoft Graph。

如果没有 Azure 订阅,可在开始前创建一个试用帐户

先决条件

在应用上启用托管标识

如果通过 Visual Studio 创建和发布 Web 应用,则已在应用上启用了托管标识。

  1. 在应用服务中,在左侧窗格中选择“标识”,然后选择“系统分配” 。

  2. 验证“状态”是否设置为“打开” 。 如果不是,请依次选择“保存”和“是”以启用系统分配的托管标识 。 启用托管标识后,状态将设置为“启用”并且对象 ID 可用。

  3. 记下“对象 ID”值,下一步骤需要使用此值。

Screenshot that shows the system-assigned identity.

授予对 Microsoft Graph 的访问权限

在访问 Microsoft Graph 时,对于要执行的操作,托管标识需要具有适当的权限。 目前,没有通过 Azure 门户分配此类权限的选项。

  1. 运行下面的脚本以添加请求的对托管标识服务主体对象的 Microsoft Graph API 权限。

    # Install the module.
    # Install-Module Microsoft.Graph -Scope CurrentUser
    
    # The tenant ID
    $TenantId = "11111111-1111-1111-1111-111111111111"
    
    # The name of your web app, which has a managed identity.
    $webAppName = "SecureWebApp-20201106120003" 
    $resourceGroupName = "SecureWebApp-20201106120003ResourceGroup"
    
    # The name of the app role that the managed identity should be assigned to.
    $appRoleName = "User.Read.All"
    
    # Get the web app's managed identity's object ID.
    Connect-AzAccount -Environment AzureChinaCloud -Tenant $TenantId
    $managedIdentityObjectId = (Get-AzWebApp -ResourceGroupName $resourceGroupName -Name $webAppName).identity.principalid
    
    Connect-MgGraph -Environment China -TenantId $TenantId -Scopes 'Application.Read.All','AppRoleAssignment.ReadWrite.All'
    
    # Get Microsoft Graph app's service principal and app role.
    $serverApplicationName = "Microsoft Graph"
    $serverServicePrincipal = (Get-MgServicePrincipal -Filter "DisplayName eq '$serverApplicationName'")
    $serverServicePrincipalObjectId = $serverServicePrincipal.Id
    
    $appRoleId = ($serverServicePrincipal.AppRoles | Where-Object {$_.Value -eq $appRoleName }).Id
    
    # Assign the managed identity access to the app role.
    New-MgServicePrincipalAppRoleAssignment `
        -ServicePrincipalId $managedIdentityObjectId `
        -PrincipalId $managedIdentityObjectId `
        -ResourceId $serverServicePrincipalObjectId `
        -AppRoleId $appRoleId
    
  2. 执行该脚本后,可在 Azure 门户中验证是否已将请求的 API 权限分配给托管标识。

  3. 转到 Microsoft Entra ID,然后选择“企业应用程序”。 此窗格显示租户中的所有服务主体。 在“托管标识”中,选择托管标识的服务主体。

    如果遵循本教程,则有两个具有相同显示名称(例如“SecureWebApp2020094113531”)的服务主体。 具有主页 URL 的服务主体表示租户中的 Web 应用。 “托管标识”中显示的服务主体不应列出“主页 URL”,并且“对象 ID”应该与上一步中的托管标识的对象 ID 值匹配。

  4. 选择托管标识的服务主体。

    Screenshot that shows the All applications option.

  5. 在“概述”中选择“权限”,你将看到添加的 Microsoft Graph 权限 。

    Screenshot that shows the Permissions pane.

调用 Microsoft Graph

ChainedTokenCredentialManagedIdentityCredentialEnvironmentCredential 类用于为你的代码获取令牌凭据以授权对 Microsoft Graph 的请求。 创建 ChainedTokenCredential 类的实例,该类使用应用服务环境中的托管标识或开发环境变量来提取令牌并将其附加到服务客户端。 下面的代码示例获取经过身份验证的令牌凭据,并使用它创建服务客户端对象,该对象将获取组中的用户。

若要查看作为示例应用程序组成部分的这段代码,请参阅:

安装 Microsoft.Identity.Web.MicrosoftGraph 客户端库包

使用 .NET Core 命令行接口或 Visual Studio 中的包管理器控制台,在项目中安装 Microsoft.Identity.Web.MicrosoftGraph NuGet 包

.NET Core 命令行

打开一个命令行,并切换到包含项目文件的目录。

运行安装命令。

dotnet add package Microsoft.Identity.Web.MicrosoftGraph
dotnet add package Microsoft.Graph

程序包管理器控制台

在 Visual Studio 中打开项目/解决方案,并使用“工具”“NuGet 包管理器”“包管理器控制台”命令打开控制台。

运行安装命令。

Install-Package Microsoft.Identity.Web.MicrosoftGraph
Install-Package Microsoft.Graph

.NET 示例

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using Microsoft.Graph;
using Azure.Identity;

...

public IList<MSGraphUser> Users { get; set; }

public async Task OnGetAsync()
{
    // Create the Graph service client with a ChainedTokenCredential which gets an access
    // token using the available Managed Identity or environment variables if running
    // in development.
    var credential = new ChainedTokenCredential(
        new ManagedIdentityCredential(),
        new EnvironmentCredential());

    string[] scopes = new[] { "https://microsoftgraph.chinacloudapi.cn/.default" };

    var graphServiceClient = new GraphServiceClient(
        credential, scopes);

    List<MSGraphUser> msGraphUsers = new List<MSGraphUser>();
    try
    {
        //var users = await graphServiceClient.Users.Request().GetAsync();
        var users = await graphServiceClient.Users.GetAsync();
        foreach (var u in users.Value)
        {
            MSGraphUser user = new MSGraphUser();
            user.userPrincipalName = u.UserPrincipalName;
            user.displayName = u.DisplayName;
            user.mail = u.Mail;
            user.jobTitle = u.JobTitle;

            msGraphUsers.Add(user);
        }
    }
    catch (Exception ex)
    {
        string msg = ex.Message;
    }

    Users = msGraphUsers;
}

清理资源

如果已完成本教程,并且不再需要 Web 应用或相关资源,请清理创建的资源。

删除资源组

Azure 门户中,从门户菜单中选择“资源组”,然后选择包含应用服务和应用服务计划的资源组。

选择“删除资源组”,删除该资源组和所有资源。

Screenshot that shows deleting the resource group.

此命令可能需要几分钟才能运行。

后续步骤

在本教程中,你了解了如何执行以下操作:

  • 在 Web 应用上创建系统分配的托管标识。
  • 向托管标识添加 Azure Graph API 权限。
  • 使用托管标识从 Web 应用调用 Azure Graph。

了解如何将 .NET Core 应用Python 应用Java 应用Node.js 应用连接到数据库。