迁移应用程序以使用 Azure Service Bus 的无密码连接

必须使用帐户访问密钥或无密码连接对Azure Service Bus的应用程序请求进行身份验证。 但是,应尽可能确定应用程序中无密码连接的优先级。 本教程介绍如何从传统身份验证方法迁移到更安全、无密码的连接。

与访问密钥相关的安全风险

下面的代码示例演示如何使用包含访问密钥的connection string连接到Azure Service Bus。 创建Service Bus时,Azure自动生成这些密钥和连接字符串。 许多开发人员都倾向于使用此解决方案,因与过去使用的选项类似。 如果应用程序当前使用连接字符串,请考虑使用本文档介绍的步骤迁移到使用无密码连接。

await using ServiceBusClient client = new("<CONNECTION-STRING>");

应慎用连接字符串。 开发人员必须尽量避免在不安全的位置公开密钥。 能够访问密钥的任何人员都可以进行身份验证。 例如,如果帐户密钥被意外签入源代码管理、通过不安全的电子邮件发送或由不应具有权限的人员查看,则恶意用户访问应用程序存在风险。 请考虑改为将应用程序更新为使用无密码连接。

迁移到无密码连接

许多Azure服务通过Microsoft Entra ID和基于角色的访问控制(RBAC)支持无密码连接。 这些技术提供可靠的安全功能,可以使用Azure标识客户端库中的 DefaultAzureCredential 来实现。

重要

某些语言必须在代码中显式实现 DefaultAzureCredential,而其他语言则通过基础插件或驱动程序在内部使用 DefaultAzureCredential

DefaultAzureCredential 支持多种身份验证方法,并自动确定应在运行时使用哪种方法。 应用通过此方法能够在不同环境(本地开发与生产)中使用不同的身份验证方法,而无需实现特定于环境的代码。

可以在DefaultAzureCredential中找到搜索凭据的顺序和位置,这些顺序和位置因语言而异。 例如,在本地使用 .NET 时,DefaultAzureCredential通常会使用开发人员用来登录Visual Studio、Azure CLI或Azure PowerShell的帐户进行身份验证。 将应用部署到Azure时,DefaultAzureCredential将自动发现和使用关联的托管服务的 托管标识,例如Azure App Service。 此转换不需要进行任何代码更改。

注意

托管标识提供用于表示应用或服务的安全标识。 标识由 Azure 平台管理,不需要预配或轮换任何机密。 可以在概述文档中了解更多关于托管标识的信息。

下面的代码示例演示如何使用无密码连接连接到Service Bus。 下一部分将更详细地介绍如何为特定服务迁移到此设置。

.NET应用程序可以将 DefaultAzureCredential 实例传递到服务客户端类的构造函数中。 DefaultAzureCredential 将自动发现该环境中可用的凭据。

client = new ServiceBusClient(
    "<NAMESPACE-NAME>.servicebus.chinacloudapi.cn",
    new DefaultAzureCredential());

将应用迁移到使用无密码身份验证的步骤

以下步骤说明如何将现有应用程序迁移到使用无密码连接,而不是使用基于密钥的解决方案。 首先配置本地开发环境,然后将这些概念应用到Azure应用托管环境。 无论是直接使用访问密钥还是通过连接字符串,这些迁移步骤都应适用。

为本地开发身份验证配置角色和用户

在本地开发时,请确保访问Service Bus的用户帐户具有正确的权限。 在此示例中,你将使用 Azure Service Bus 数据所有者角色发送和接收数据,不过还可以使用更精细的角色。 若要自行分配此角色,您需要被分配 User Access Administrator 角色,或分配其他包含 Microsoft.Authorization/roleAssignments/write 操作的角色。 可以使用Azure门户、Azure CLI或Azure PowerShell向用户分配Azure RBAC 角色。 可以在范围概述页上详细了解角色分配的可用范围。

在此方案中,你将为用户帐户分配权限,其权限范围限定于特定的 Service Bus 命名空间,以遵循最低特权原则。 这种做法仅为用户提供所需的最低权限,并创建更安全的生产环境。

以下示例将Azure Service Bus数据所有者角色分配给用户帐户,以便发送和接收数据。

重要

在大多数情况下,角色分配在Azure中传播需要一两分钟,但在极少数情况下,可能需要长达 8 分钟的时间。 如果在首次运行代码时收到身份验证错误,请稍等片刻再试。

  1. 在Azure门户中,使用主搜索栏或左侧导航找到Service Bus命名空间。

  2. 在Service Bus概述页上,从左侧菜单中选择Access 控件(IAM)

  3. 在“访问控制 (IAM)”页上,选择“角色分配”选项卡。

  4. 从顶部菜单中选择“+ 添加”,然后从出现的下拉菜单中选择“添加角色分配”。

    显示如何分配角色的屏幕截图。

  5. 使用搜索框将结果筛选为所需角色。 在此示例中,搜索 Azure Service Bus 数据所有者并选择匹配结果,然后选择 Next

  6. 在“访问权限分配对象”下,选择“用户、组或服务主体”,然后选择“+ 选择成员”。

  7. 在对话框中,搜索Microsoft Entra用户名(通常是user@domain电子邮件地址),然后选择对话框底部的选择

  8. 选择“查看 + 分配”转到最后一页,然后再次选择“查看 + 分配”完成该过程。

登录并迁移应用代码以使用无密码连接

对于本地开发,请确保您使用分配给 Service Bus 命名空间角色的同一 Microsoft Entra 帐户进行身份验证。 可以通过 Azure CLI、Visual Studio、Azure PowerShell 或其他工具(如 IntelliJ)进行身份验证。

对于本地开发,请确保使用分配给该角色的同一Microsoft Entra帐户进行身份验证。 可以通过常用的开发工具(如Azure CLI或Azure PowerShell)进行身份验证。 可用于进行身份验证的开发工具因语言而异。

使用以下命令通过Azure CLI登录Azure:

az cloud set -n AzureChinaCloud
az login
# az cloud set -n AzureCloud   //means return to Public Azure.

接下来,更新代码以使用无密码连接。

  1. 若要在 .NET 应用程序中使用 DefaultAzureCredential,请安装 Azure.Identity 包:

    dotnet add package Azure.Identity
    
  2. 在文件的顶部,添加以下代码:

    using Azure.Identity;
    
  3. 标识创建要连接到Azure Service Bus的 ServiceBusClient 对象的代码。 更新代码,使之与以下示例一致:

     var serviceBusNamespace = $"{namespace}.servicebus.chinacloudapi.cn";
     ServiceBusClient client = new(
         serviceBusNamespace,
         new DefaultAzureCredential());
    

在本地运行应用

进行这些代码更改后,在本地运行应用程序。 新配置应选取本地凭据,例如 Azure CLI、Visual Studio 或 IntelliJ。 Azure中分配给本地开发用户的角色允许应用在本地连接到Azure服务。

配置Azure托管环境

将应用程序配置为使用无密码连接并在本地运行后,相同的代码可以在部署到Azure时向Azure服务进行身份验证。 例如,部署到启用了托管标识的Azure App Service实例的应用程序可以连接到Azure Service Bus。

使用 Azure 门户创建托管标识

以下步骤演示如何为各种 Web 托管服务创建系统分配的托管标识。 托管标识可以使用之前设置的应用配置安全地连接到其他Azure服务。

  1. 在Azure App Service实例的主概述页上,从左侧导航中选择Identity

  2. 在“系统分配”选项卡下,确保将“状态”字段设置为“启用”。 系统分配的身份标识由Azure内部管理,代你处理管理任务。 身份的详细信息和 ID 永远不会在代码中被暴露。

    屏幕截图显示如何创建系统分配的托管标识。

或者,您还可以使用 Azure CLI,在 Azure 托管环境中启用托管身份。

可以使用服务连接器在Azure计算托管环境和目标服务之间使用 Azure CLI创建连接。 CLI 会自动处理创建托管标识并分配适当的角色,如门户说明中所述。

如果使用Azure App Service,请使用 az webapp connection 命令:

az webapp connection create servicebus \
    --resource-group <resource-group-name> \
    --name <webapp-name> \
    --target-resource-group <target-resource-group-name> \
    --namespace <target-service-bus-namespace> \
    --system-identity

如果使用 Azure Spring Apps,请使用 az spring connection 命令:

az spring connection create servicebus \
    --resource-group <resource-group-name> \
    --service <service-instance-name> \
    --app <app-name> \
    --deployment <deployment-name> \
    --target-resource-group <target-resource-group> \
    --namespace <target-service-bus-namespace> \
    --system-identity

如果使用Azure Container Apps,请使用 az containerapp connection 命令:

az containerapp connection create servicebus \
    --resource-group <resource-group-name> \
    --name <webapp-name> \
    --target-resource-group <target-resource-group-name> \
    --namespace <target-service-bus-namespace> \
    --system-identity

为托管标识分配角色

接下来,您需要为创建的托管身份授予访问您的服务总线的权限。 将角色分配给托管标识,就像为你的本地开发用户所做的那样。

如果使用服务连接器连接服务,则无需完成此步骤。 已为你完成必要的配置:

  • 如果在创建连接时选择了托管标识,则会为应用创建系统分配的托管标识,并在Service Bus上分配了 Azure Service Bus 数据所有者角色。

  • 如果选择了connection string,则connection string已添加为应用环境变量。

测试应用程序

进行这些代码更改后,在浏览器中浏览到托管应用程序。 应用应能够成功连接到Service Bus。 请记住,角色分配可能需要几分钟才能通过Azure环境传播。 应用程序现在配置为在本地和生产环境中运行,开发人员无需管理应用程序本身的机密。

后续步骤

本教程介绍了如何将应用程序迁移到无密码连接。