教程:从 .NET 守护程序应用调用受保护的 Web API

适用于:带白色勾号的绿色圆圈。 员工租户 带白色勾号的绿色圆圈。 外部租户(了解详细信息

本教程演示如何从 .NET 守护程序应用调用受保护的 Web API。 允许客户端守护程序应用使用自己的标识获取访问令牌,然后调用 Web API。 在本例中,我们调用受保护的 Microsoft Graph 终结点。

在本教程中;

  • 配置守护程序应用以使用其应用注册详细信息。 确保向应用授予对 Microsoft Graph API 的 User.Read.All 权限。
  • 构建守护程序应用,它代表其自己获取令牌并调用受保护的 Web API。

先决条件

  • .NET 在本教程中,我们使用 .NET 9.0。
  • Visual Studio Code 或其他代码编辑器。
  • 租户中的应用注册。 确保从应用注册详细信息中获取以下内容:
    • 你注册的客户端 Web 应用的应用程序(客户端)ID
    • 注册 Web 应用的“目录(租户) ID”
    • 你创建的 Web 应用的客户端密码值。

创建 .NET 守护程序应用

  1. 打开终端并导航到希望项目所在的文件夹。

  2. 初始化 .NET 控制台应用并导航到其根文件夹。

    dotnet new console -n DotnetDaemon
    cd DotnetDaemon
    

安装软件包

安装 Microsoft.Identity.WebMicrosoft.Identity.Web.DownstreamApi 包:

dotnet add package Microsoft.Identity.Web
dotnet add package Microsoft.Identity.Web.DownstreamApi

Microsoft.Identity.Web 提供 ASP.NET Core、身份验证中间件和用于 .NET 的Microsoft身份验证库(MSAL)之间的粘附,使你能够更轻松地向应用添加身份验证和授权功能。 Microsoft.Identity.Web.DownstreamApi 提供用于调用下游 API 的接口。

创建 appsettings.json 文件,并添加注册配置

  1. 在应用的根文件夹中创建 appsettings.json 文件。

  2. 将应用注册详细信息添加到 appsettings.json 文件中。

    {
        "AzureAd": {
            // "Authority": "", you can use this for customer tenants in place of Instance and TenantId values
            "Instance": "https://login.microsoftonline.com/",
            "TenantId": "Enter_the_Tenant_ID_Here",
            "ClientId": "Enter_the_Application_ID_Here",
            "ClientCredentials": [
                {
                    "SourceType": "ClientSecret",
                    "ClientSecret": "Enter_the_Client_Secret_Here"
                }
            ]
        },
        "DownstreamApi": {
            "BaseUrl": "https://graph.microsoft.com",
            "RelativePath": "/v1.0/users/",
            "RequestAppToken": true,
            "Scopes": [
                "https://graph.microsoft.com/.default"
            ]
        }
    }
    

    将以下值替换为你自己的值:

    价值 DESCRIPTION
    Enter_the_Application_ID_Here 注册的客户端守护程序应用的应用程序(客户端)ID。
    Enter_the_Client_Secret_Here 已创建的守护程序应用机密值。
    Enter_the_Tenant_ID_Here 注册了应用的目录/租户的租户 ID。

    注释

    对于在外部租户中注册的应用,可以使用 Authority 并删除 InstanceTenantId

    "Authority": "https://<Enter_the_Tenant_Subdomain_Here>.ciamlogin.com/"。 其中 Enter_the_Tenant_Subdomain_Here 是租户的子域。

  3. appsettings.json 文件添加到项目文件。 项目文件是项目中的 .csproj 文件。 这是因为需要将文件复制到输出目录。

    <ItemGroup>
        <None Update="appsettings.json">
            <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </None>
    </ItemGroup>
    

获取访问令牌

  1. 在代码编辑器中打开program.cs文件并删除其内容。

  2. 将包添加到文件。

    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Identity.Abstractions;
    using Microsoft.Identity.Web;
    
  3. 创建令牌获取实例。 使用Microsoft.Identity.Web包的TokenAcquirerFactory类中的GetDefaultInstance方法生成令牌获取实例。 默认情况下,如果实例与应用位于同一文件夹中,则读取 appsettings.json 文件。 GetDefaultInstance 还允许我们向服务集合添加服务。

    将此代码行添加到 program.cs 文件:

    var tokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance();
    
  4. 配置要从配置中读取的应用程序选项,并添加 DownstreamApi 服务。 该服务 DownstreamApi 提供用于调用下游 API 的接口。 我们在配置对象中调用此服务 DownstreamAPI 。 守护程序应用从 appsettings.json“DownstreamApi”部分读取下游 API 配置。 默认情况下,你将获得内存中令牌缓存。

    将以下代码片段添加到 program.cs 文件:

    const string ServiceName = "DownstreamApi";
    
    tokenAcquirerFactory.Services.AddDownstreamApi(ServiceName,
        tokenAcquirerFactory.Configuration.GetSection("DownstreamApi"));
    

    调用的下游 API 是 Microsoft Graph。 在本教程中,我们使用 DownstreamApi 该服务。 还可以使用 Microsoft Graph SDK。

  5. 生成令牌获取器。 这将组合您添加的所有服务并返回一个服务提供方。 使用此服务提供商获取对所添加的 API 资源的访问权限。 在这种情况下,仅将一个 API 资源添加为要访问的下游服务。

    将以下代码片段添加到 program.cs 文件:

    var serviceProvider = tokenAcquirerFactory.Build();
    

调用 Web API

  1. 添加代码以使用 IDownstreamApi 接口调用受保护的 Web API。 在本教程中,我们将调用 Microsoft Graph API 终结点。

  2. 将此代码添加到 program.cs 文件:

    try
    {
        IDownstreamApi downstreamApi = serviceProvider.GetRequiredService<IDownstreamApi>();
    
        var response = await downstreamApi.GetForAppAsync<HttpResponseMessage>("DownstreamApi");
        var content = await response.Content.ReadAsStringAsync();
        var statusCode = response.StatusCode;
    
        Console.WriteLine($"Response status code: {statusCode}");
    
        if (!content.Any())
        {
            Console.WriteLine("There are no users to display.");
            return;
        }
    
        Console.WriteLine(content);
    }
    catch (Exception ex) { Console.WriteLine("We could not retrieve the user's list: " + $"{ex}"); }
    

    该代码调用在 appsettings.json 文件中定义的终结点。 IDownstreamApi 接口的GetForAppAsync 方法用于调用终结点。 应用程序代表自己发起请求。 该方法返回一个 HttpResponseMessage 对象。 然后,响应将读取为字符串并在控制台中显示。

运行客户端守护程序应用

导航到守护程序应用的根文件夹并运行以下命令:

dotnet run

如果一切正常,则应在终端中看到 “响应状态代码:确定 ”。 如果有用户,则用户列在终端中,否则会看到消息 “没有要显示的用户”。

如果发生任何错误,终端中会显示错误消息。

故障排除

如果遇到错误,

  • 确认添加到 appsettings.json 文件的注册详细信息。
  • 确认已将 appsettings.json 文件添加到项目文件。
  • 确认应用权限已正确配置。