Compartir a través de

使用托管标识从 Web 应用访问 Azure 存储

了解如何使用托管标识为 Azure 应用服务上运行的 Web 应用(不是登录用户)访问 Azure 存储。

关系图展示如何访问存储。

你要从 Web 应用添加对 Azure 数据平面(Azure 存储、Azure SQL 数据库、Azure Key Vault 或其他服务)的访问权限。 你可以使用共享密钥,但之后需要考虑操作安全性:谁可以创建、部署和管理机密。 还可能会将此密钥签入 GitHub,黑客知道如何扫描它。 向 Web 应用授予数据访问权限的更安全方法是使用托管标识

Microsoft Entra ID 中的托管标识允许应用服务通过基于角色的访问控制 (RBAC) 访问资源,而不要求使用应用凭据。 向 Web 应用分配托管标识之后,Azure 会负责创建和分发证书。 用户无需费心管理机密或应用凭据。

在本教程中,你将了解:

  • 在 Web 应用上创建系统分配的托管标识。
  • 创建存储帐户和 Azure Blob 存储容器。
  • 使用托管标识从 Web 应用访问存储。

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

先决条件

在应用上启用托管标识

如果通过 Visual Studio 创建和发布 Web 应用,则已在应用上启用了托管标识。 在应用服务中,在左侧窗格中选择“标识”,然后选择“系统分配” 。 验证“状态”是否设置为“打开” 。 如果不是,请依次选择“保存”和“是”以启用系统分配的托管标识 。 启用托管标识后,状态将设置为“启用”并且对象 ID 可用。

屏幕截图中显示“系统分配的标识”选项。

此步骤创建一个新的对象 ID,该 ID 不同于在“身份验证/授权”窗格中创建的应用 ID。 复制系统分配的托管标识的对象 ID。 稍后需要用到此信息。

创建存储帐户和 Blob 存储容器

现在可以创建存储帐户和 Blob 存储容器。

每个存储帐户都必须属于 Azure 资源组。 资源组是对 Azure 资源进行分组的逻辑容器。 创建存储帐户时,可以选择创建新的资源组,或者使用现有的资源组。 本文介绍如何创建新资源组。

可以使用常规用途 v2 存储帐户访问所有 Azure 存储服务:Blob、文件、队列、表和磁盘。 本文所述的步骤将创建常规用途 v2 存储帐户,但创建任何类型的存储帐户的步骤都相似。

Azure 存储中的 Blob 已组织成容器。 你需要先创建容器,然后才能在本教程的稍后部分上传 Blob。

若要在 Azure 门户中创建常规用途 v2 存储帐户,请执行以下步骤。

  1. 在 Azure 门户菜单中,选择“所有服务” 。 在资源列表中输入“存储帐户”。 开始键入时,会根据输入筛选该列表。 选择“存储帐户” 。

  2. 在显示的“存储帐户”窗口中,选择“创建”。

  3. 选择要在其中创建存储帐户的订阅。

  4. 在“资源组”字段下,从下拉菜单中选择包含你的 Web 应用的资源组。

  5. 然后,输入存储帐户的名称。 所选名称在 Azure 中必须唯一。 该名称还必须为 3 到 24 个字符,并且只能包含数字和小写字母。

  6. 选择存储帐户的位置或使用默认位置。

  7. 对于“性能”,请选择“标准”选项。

  8. 对于“冗余”,请从下拉列表中选择“本地冗余存储 (LRS)”选项。

  9. 选择“审阅”可查看存储帐户设置并创建帐户。

  10. 选择“创建” 。

若要在 Azure 存储中创建 Blob 存储容器,请执行以下步骤。

  1. 转到 Azure 门户中的新存储帐户。

  2. 在存储帐户的左侧菜单中,滚动到“数据存储”部分,然后选择“容器”。

  3. 选择“+ 容器”。

  4. 为新容器键入名称。 容器名称必须小写,必须以字母或数字开头,并且只能包含字母、数字和短划线 (-) 字符。

  5. 设置容器的公共访问权限级别。 默认级别为“专用(禁止匿名访问)”。

  6. 选择“创建”创建容器。

授予对存储帐户的访问权限

你需要先向 Web 应用授予对存储帐户的访问权限,然后才能创建、读取或删除 Blob。 在上一步骤中,你使用托管标识配置了在应用服务上运行的 Web 应用。 使用 Azure RBAC,可以向托管标识授予对其他资源的访问权限,这一点与所有安全主体一样。 “存储 Blob 数据参与者”角色向 Web 应用(由系统分配的托管标识表示)授予对 Blob 容器和数据的读取、写入和删除访问权限。

注意

Azure RBAC 不支持专用 Blob 容器上的某些操作,例如查看 Blob 或在帐户之间复制 Blob。 具有专用访问级别的 Blob 容器需要 SAS 令牌才能执行未经 Azure RBAC 授权的任何操作。 有关详细信息,请参阅何时使用共享访问签名

Azure 门户中,进入你的存储帐户,向 Web 应用授予访问权限。 依次选择左侧窗格中的“访问控制(IAM)”、“角色分配” 。 你将看到有权访问存储帐户的用户的列表。 现在,你要向机器人(需要访问存储帐户的应用服务)添加角色分配。 选择“添加”>“添加角色分配”,打开“添加角色分配”页面 。

  1. 在“分配类型”选项卡中,选择“作业函数类型”,然后选择“下一步”。

  2. 在“角色”选项卡中,从下拉列表中选择“存储 Blob 数据参与者”角色,然后选择“下一步”。

  3. 在“成员”选项卡中,选择“将访问权限分配给”->“托管标识”,然后选择“成员”->“选择成员”。 在“选择托管标识”窗口中,在“托管标识”下拉列表中查找并选择为应用服务创建的托管标识。 选择“选择”按钮 。

  4. 选择“查看并分配”,然后再次选择“查看并分配”。

有关详细步骤,请参阅使用 Azure 门户分配 Azure 角色

Web 应用现在可以访问存储帐户。

访问 Blob 存储

DefaultAzureCredential 类用于获取代码的令牌凭据,以授权对 Azure 存储的请求。 创建 DefaultAzureCredential 类的实例,该类使用托管标识提取令牌并将其附加到服务客户端。 下面的代码示例获取经过身份验证的令牌凭据,并使用它创建服务客户端对象,该对象将上传新的 Blob。

若要查看作为示例应用程序一部分的代码,请参阅 GitHub 上的示例

安装客户端库包

安装要与 Blob 存储一起使用的 Blob 存储 NuGet 包,并安装适用于 .NET NuGet 包的 Azure 标识客户端库以使用 Microsoft Entra 凭据进行身份验证。 使用 .NET 命令行接口 (CLI) 或 Visual Studio 中的包管理器控制台,在项目中安装客户端库。

.NET CLI

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

运行安装命令。

dotnet add package Azure.Storage.Blobs

dotnet add package Azure.Identity

程序包管理器控制台

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

运行安装命令。

Install-Package Azure.Storage.Blobs

Install-Package Azure.Identity

示例

using System;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Text;
using System.IO;
using Azure.Identity;

// Some code omitted for brevity.

static public async Task UploadBlob(string accountName, string containerName, string blobName, string blobContents)
{
    // Construct the blob container endpoint from the arguments.
    string containerEndpoint = string.Format("https://{0}.blob.core.chinacloudapi.cn/{1}",
                                                accountName,
                                                containerName);

    // Get a credential and create a client object for the blob container.
    BlobContainerClient containerClient = new BlobContainerClient(new Uri(containerEndpoint),
                                                                    new DefaultAzureCredential());

    try
    {
        // Create the container if it does not exist.
        await containerClient.CreateIfNotExistsAsync();

        // Upload text to a new block blob.
        byte[] byteArray = Encoding.ASCII.GetBytes(blobContents);

        using (MemoryStream stream = new MemoryStream(byteArray))
        {
            await containerClient.UploadBlobAsync(blobName, stream);
        }
    }
    catch (Exception e)
    {
        throw e;
    }
}

清理资源

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

后续步骤