你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
迁移应用程序以将无密码连接用于 Azure Blob 存储
必须使用帐户访问密钥或无密码连接等配置对 Azure 服务的应用程序请求进行身份验证。 但是,应尽可能确定应用程序中无密码连接的优先级。 使用密码或密钥的传统身份验证方法会产生安全风险和复杂性。 访问 Azure 服务中心的无密码连接,详细了解迁移到无密码连接的优势。
以下教程介绍了如何使用无密码连接迁移现有应用程序以进行连接。 无论是使用访问密钥、连接字符串还是其他基于机密的方法,都适用这些相同的迁移步骤。
在本地开发时,请确保访问 Blob 数据的用户帐户具有正确的权限。 需有“存储 Blob 数据参与者”角色才能读取和写入 Blob 数据。 若要为你自己分配此角色,需要具有“用户访问管理员”角色,或者具有包含 Microsoft.Authorization/roleAssignments/write 操作的其他角色。 可使用 Azure 门户、Azure CLI 或 Azure PowerShell 向用户分配 Azure RBAC 角色。 可以在范围概述页上详细了解角色分配的可用范围。
在此方案中,你将为用户帐户分配权限(范围为存储帐户)以遵循最低权限原则。 这种做法仅为用户提供所需的最低权限,并创建更安全的生产环境。
以下示例将“存储 Blob 数据参与者”角色分配给用户帐户,该角色提供对存储帐户中 Blob 数据的读取和写入访问权限。
重要
在大多数情况下,角色分配在 Azure 中传播需要一两分钟的时间,但极少数情况下最多可能需要 8 分钟。 如果在首次运行代码时收到身份验证错误,请稍等片刻再试。
在 Azure 门户中,使用主搜索栏或左侧导航找到存储帐户。
在存储帐户概述页的左侧菜单中选择“访问控制 (IAM)”。
在“访问控制 (IAM)”页上,选择“角色分配”选项卡。
从顶部菜单中选择“+ 添加”,然后从出现的下拉菜单中选择“添加角色分配”。
使用搜索框将结果筛选为所需角色。 在此示例中,搜索“存储 Blob 数据参与者”并选择匹配的结果,然后选择“下一步”。
在“访问权限分配对象”下,选择“用户、组或服务主体”,然后选择“+ 选择成员”。
在对话框中,搜索 Microsoft Entra ID 用户名(通常是 user@domain 电子邮件地址),然后选中对话框底部的“选择”。
选择“查看 + 分配”转到最后一页,然后再次选择“查看 + 分配”完成该过程。
若要使用 Azure CLI 在资源级别分配角色,必须先使用 az storage account show
命令检索资源 ID。 可以使用 --query
参数筛选输出属性。
az storage account show --resource-group '<your-resource-group-name>' --name '<your-storage-account-name>' --query id
复制上述命令的输出 Id
。 然后,可以使用 Azure CLI 的 az role 命令分配角色。
az role assignment create --assignee "<user@domain>" \
--role "Storage Blob Data Contributor" \
--scope "<your-resource-id>"
若要使用 Azure PowerShell 在资源级别分配角色,首先必须使用 Get-AzResource
命令检索资源 ID。
Get-AzResource -ResourceGroupName "<yourResourceGroupname>" -Name "<yourStorageAccountName>"
复制上述命令输出中的 Id
值。 然后,可以使用 PowerShell 中的 New-AzRoleAssignment 命令分配角色。
New-AzRoleAssignment -SignInName <user@domain> `
-RoleDefinitionName "Storage Blob Data Contributor" `
-Scope <yourStorageAccountId>
登录并迁移应用代码以使用无密码连接
对于本地开发,请确保使用分配了该角色的同一 Microsoft Entra 帐户进行身份验证。 可以通过常用的开发工具(如 Azure CLI 或 Azure PowerShell)进行身份验证。 可用于进行身份验证的开发工具因语言而异。
使用以下命令通过 Azure CLI 登录到 Azure:
az login
选择 Visual Studio 右上角的“登录”按钮。
使用你之前为其分配角色的 Microsoft Entra 帐户登录。
需要安装 Azure CLI 才能通过 Visual Studio Code 使用 DefaultAzureCredential
。
在 Visual Studio Code 的主菜单上,导航到“终端”>“新建终端”。
使用以下命令通过 Azure CLI 登录到 Azure:
az login
通过以下命令使用 PowerShell 登录到 Azure:
Connect-AzAccount
接下来,更新代码以使用无密码连接。
若要在 .NET 应用程序中使用 DefaultAzureCredential
,请安装 Azure.Identity
包:
dotnet add package Azure.Identity
在文件的顶部,添加以下代码:
using Azure.Identity;
确定代码中创建 BlobServiceClient
以连接到 Azure Blob 存储的位置。 更新代码,使之与以下示例一致:
DefaultAzureCredential credential = new();
BlobServiceClient blobServiceClient = new(
new Uri($"https://{storageAccountName}.blob.core.windows.net"),
credential);
若要在 Go 应用程序中使用 DefaultAzureCredential
,请安装 azidentity
模块:
go get -u github.com/Azure/azure-sdk-for-go/sdk/azidentity
在文件的顶部,添加以下代码:
import (
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
)
确定代码中创建 Client
实例以连接到 Azure Blob 存储的位置。 更新代码,使之与以下示例一致:
cred, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
// handle error
}
serviceURL := fmt.Sprintf("https://%s.blob.core.windows.net", storageAccountName)
client, err := azblob.NewClient(serviceURL, cred, nil)
if err != nil {
// handle error
}
若要在 Java 应用程序中使用 DefaultAzureCredential
,请通过以下方法之一安装 azure-identity
包:
- 包括 BOM 文件。
- 包括直接依赖项。
在文件的顶部,添加以下代码:
import com.azure.identity.DefaultAzureCredentialBuilder;
确定代码中创建 BlobServiceClient
对象以连接到 Azure Blob 存储的位置。 更新代码,使之与以下示例一致:
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder()
.build();
String endpoint =
String.format("https://%s.blob.core.windows.net", storageAccountName);
BlobServiceClient blobServiceClient = new BlobServiceClientBuilder()
.endpoint(endpoint)
.credential(credential)
.buildClient();
若要在 Node.js 应用程序中使用 DefaultAzureCredential
,请安装 @azure/identity
包:
npm install --save @azure/identity
在文件的顶部,添加以下代码:
import { DefaultAzureCredential } from "@azure/identity";
确定代码中创建 BlobServiceClient
对象以连接到 Azure Blob 存储的位置。 更新代码,使之与以下示例一致:
const credential = new DefaultAzureCredential();
const blobServiceClient = new BlobServiceClient(
`https://${storageAccountName}.blob.core.windows.net`,
credential
);
若要在 Python 应用程序中使用 DefaultAzureCredential
,请安装 azure-identity
包:
pip install azure-identity
在文件的顶部,添加以下代码:
from azure.identity import DefaultAzureCredential
确定代码中创建 BlobServiceClient
对象以连接到 Azure Blob 存储的位置。 更新代码,使之与以下示例一致:
credential = DefaultAzureCredential()
blob_service_client = BlobServiceClient(
account_url = "https://%s.blob.core.windows.net" % storage_account_name,
credential = credential
)
请确保在 BlobServiceClient
的 URI 中更新存储帐户名称。 可以在 Azure 门户的概述页上找到存储帐户名称。
在本地运行应用
进行这些代码更改后,在本地运行应用程序。 新配置应选取本地凭据,例如 Azure CLI、Visual Studio 或 IntelliJ。 你在 Azure 中分配给本地开发用户的角色将允许应用在本地连接到 Azure 服务。
将应用程序配置为使用无密码连接并在本地运行后,相同的代码可以在应用程序部署到 Azure 后向 Azure 服务进行身份验证。 以下各部分介绍了如何配置已部署的应用程序,以使用托管标识连接到 Azure Blob 存储。
创建托管标识
你可以使用 Azure 门户或 Azure CLI 创建用户分配的托管标识。 应用程序将使用该标识向其他服务进行身份验证。
- 在 Azure 门户顶部搜索“托管标识”。 选择“托管标识”结果。
- 选择“托管标识”概述页面顶部的“+ 创建”。
- 在“基本信息”选项卡中,输入以下值:
- “订阅”:选择所需的订阅。
- “资源组”:选择所需的资源组。
- 区域:选择你所在位置附近的区域。
- “名称”:输入标识的可识别名称,例如“MigrationIdentity”。
- 在页面底部选择“查看 + 创建”。
- 验证检查完成后,选择“创建”。 Azure 将创建新的用户分配的标识。
创建资源后,选择“转到资源”以查看托管标识的详细信息。
使用 az identity create 命令创建用户分配的托管标识:
az identity create --name MigrationIdentity --resource-group <your-resource-group>
将托管标识与 Web 应用相关联
你需要将 Web 应用配置为使用自己创建的托管标识。 使用 Azure 门户或 Azure CLI 将标识分配给应用。
在 Azure 门户中完成以下步骤,从而将标识与应用相关联。 这些步骤同样也适用于以下 Azure 服务:
- Azure Spring Apps
- Azure Container Apps
- Azure 虚拟机
- Azure Kubernetes 服务
导航到 Web 应用的概述页面。
从左侧导航菜单中,选择“标识”。
在“标识”页面上,切换到“用户分配的”选项卡。
选择“+ 添加”,打开“添加用户分配的托管标识”浮出控件。
选择之前用于创建标识的订阅。
按名称搜索“MigrationIdentity”,并从搜索结果中选择该标识。
选择“添加”,以将该标识与应用相关联。
使用以下 Azure CLI 命令将标识与应用相关联:
使用 az identity show 命令检索创建的托管标识的 ID。 复制输出值以在下一步中使用。
az identity show --name MigrationIdentity -g <your-identity-resource-group-name> --query id
可以使用 az webapp identity assign 命令将托管标识分配给 Azure 应用服务实例。
az webapp identity assign \
--resource-group <resource-group-name> \
--name <webapp-name>
--identities <managed-identity-id>
可以使用 az spring app identity assign 命令将托管标识分配给 Azure Spring Apps 实例。
az spring app identity assign \
--resource-group <resource-group-name> \
--name <app-name> \
--service <service-name>
--user-assigned <managed-identity-id>
你可以使用 az vm identity assign 命令将托管标识分配给虚拟机。
az containerapp identity assign \
--resource-group <resource-group-name> \
--name <app-name>
--user-assigned <managed-identity-id>
可以使用 az vm identity assign 命令将托管标识分配给虚拟机。
az vm identity assign \
--resource-group <resource-group-name> \
--name <virtual-machine-name>
--identities <managed-identity-id>
可以使用 az aks update 命令将托管标识分配给 Azure Kubernetes 服务 (AKS) 实例。
az aks update \
--resource-group <resource-group-name> \
--name <cluster-name> \
--enable-managed-identity \
--assign-identity <managed-identity-id> \
--assign-kubelet-identity <managed-identity-id>
可以使用 Azure CLI 通过服务连接器在 Azure 计算托管环境和目标服务之间创建连接。 该服务连接器 CLI 命令会自动将适当的角色分配给标识。 可以在概述页上详细了解服务连接器以及支持哪些方案。
使用 az identity show
命令检索创建的托管标识的客户端 ID。 复制该值供以后使用。
az identity show --name MigrationIdentity --resource-group <your-resource-group> --query clientId
使用相应的 CLI 命令建立服务连接:
如果使用的是某个 Azure 应用服务,请使用 az webapp connection 命令:
az webapp connection create storage-blob \
--resource-group <resource-group-name> \
--name <webapp-name> \
--target-resource-group <target-resource-group-name> \
--account <target-storage-account-name> \
--user-identity "client-id=<your-identity-client-id>" "subs-id=<your-subscription-id>"
如果你使用的是 Azure Spring Apps,请使用 az spring connection 命令:
az spring connection create storage-blob \
--resource-group <resource-group-name> \
--service <service-instance-name> \
--app <app-name> \
--deployment <deployment-name> \
--target-resource-group <target-resource-group> \
--account <target-storage-account-name> \
--user-identity "client-id=<your-identity-client-id>" "subs-id=<your-subscription-id>"
如果使用的是 Azure 容器应用,请使用 az containerapp connection 命令:
az containerapp connection create storage-blob \
--resource-group <resource-group-name> \
--name <containerapp-name> \
--target-resource-group <target-resource-group-name> \
--account <target-storage-account-name> \
--user-identity "client-id=<your-identity-client-id>" "subs-id=<your-subscription-id>"
为托管标识分配角色
接下来,需要向创建的托管标识授予访问存储帐户的权限。 通过为托管标识分配角色来授予权限,就像对本地开发用户的操作一样。
导航到存储帐户概述页,并在左侧导航栏中选择“访问控制 (IAM)”。
选择“添加角色分配”
在“角色”搜索框中,搜索“存储 Blob 数据参与者”,这是用于管理 Blob 数据操作的常用角色。 可以分配适合你的用例的任何角色。 从列表中选择“存储 Blob 数据参与者”,然后选择“下一步”。
在“添加角色分配”屏幕上,针对“将访问权限分配给”选项,请选择“托管标识”。 然后选择“+选择成员”。
在浮出控件中,按名称搜索创建的托管标识,并从结果中选择该标识。 选择“选择”以关闭浮出控件菜单。
多次选择“下一步”,直到可以选择“查看 + 分配”,从而完成角色分配。
若要使用 Azure CLI 在资源级别分配角色,必须先使用 az storage account show 命令检索资源 ID。 可以使用 --query
参数筛选输出属性。
az storage account show \
--resource-group '<your-resource-group-name>' \
--name '<your-storage-account-name>' \
--query id
复制上述命令中的输出 ID。 然后,可以使用 Azure CLI 的 az role assignment 命令分配角色。
az role assignment create \
--assignee "<your-username>" \
--role "Storage Blob Data Contributor" \
--scope "<your-resource-id>"
如果使用服务连接器连接服务,则无需完成此步骤。 在你运行服务连接器 CLI 命令时,系统已为你处理必要的角色配置。
更新应用程序代码
需要配置应用程序代码,以查找在部署到 Azure 时创建的特定托管标识。 在某些情况下,显式设置应用的托管标识还可以防止其他环境标识被意外检测到并自动使用。
在托管标识概述页面上,将客户端 ID 值复制到剪贴板。
应用以下特定于语言的更改:
创建一个 DefaultAzureCredentialOptions
对象并将其传递给 DefaultAzureCredential
。 将 ManagedIdentityClientId 属性设置为客户端 ID。
DefaultAzureCredential credential = new(
new DefaultAzureCredentialOptions
{
ManagedIdentityClientId = managedIdentityClientId
});
将 AZURE_CLIENT_ID
环境变量设置为托管标识客户端 ID。 DefaultAzureCredential
读取此环境变量。
调用 managedIdentityClientId 方法。 将客户端 ID 传递给它。
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder()
.managedIdentityClientId(managedIdentityClientId)
.build();
创建一个 DefaultAzureCredentialClientIdOptions
对象,其 managedIdentityClientId 属性设置为客户端 ID。 将该对象传递给 DefaultAzureCredential
构造函数。
const credential = new DefaultAzureCredential({
managedIdentityClientId
});
将 DefaultAzureCredential
构造函数的 managed_identity_client_id 参数设置为客户端 ID。
credential = DefaultAzureCredential(
managed_identity_client_id = managed_identity_client_id
)
进行此更改后,将代码重新部署到 Azure,以便应用配置更新。
测试应用程序
部署更新后的代码后,请在浏览器中导航到你的托管应用程序。 应用应能够成功连接到存储帐户。 请记住,角色分配通过 Azure 环境传播最长可能需要五分钟的时间。 应用程序现在配置为在本地和生产环境中运行,开发人员无需管理应用程序本身的机密。
后续步骤
本教程介绍了如何将应用程序迁移到无密码连接。
可以阅读以下资源,更深入地了解本文中讨论的概念: