从本地托管的 JavaScript 应用向 Azure 资源进行身份验证

托管在 Azure 外部的应用(例如本地或第三方数据中心)应通过 Microsoft Entra ID 使用应用程序服务主体向 Azure 服务进行身份验证。 在前面的部分中,你将了解:

  • 如何使用 Microsoft Entra 注册应用程序以创建服务主体
  • 如何将角色分配到范围权限
  • 如何使用应用代码中的服务主体进行身份验证

使用专用应用程序服务主体,可以在访问 Azure 资源时遵守最低特权原则。 权限仅限于开发期间应用的特定要求,从而防止意外访问适用于其他应用或服务的 Azure 资源。 此方法还有助于避免在应用移至生产环境时出现的问题,确保其在开发环境中不拥有过多权限。

应为托管应用的每个环境创建不同的应用注册。 这允许为每个服务主体配置特定于环境的资源权限,并确保部署到一个环境的应用不会与另一环境中的 Azure 资源通信。

在 Azure 中注册应用

使用 Azure 门户或 Azure CLI 通过 Azure 中的应用注册创建应用程序服务主体对象。

  1. 在 Azure 门户中,使用搜索栏导航到 应用注册 页。

  2. 在“应用注册”页上,选择“+ 新建注册”。

  3. 在“注册应用程序”页面上:

    • 对于 名称 字段,请输入包含应用名称和目标环境的描述性值。
    • 对于支持的帐户类型,请仅选择此组织目录中的帐户(仅限 Microsoft 客户引导 - 单租户),或选择最能满足你的要求的选项。
  4. 选择 注册 以注册应用并创建服务主体。

    显示如何在 Azure 门户中创建应用注册的屏幕截图。

  5. 在应用的 应用注册 页上,复制 应用程序(客户端)ID目录(租户)ID 并将其粘贴到临时位置,以便在应用代码配置中稍后使用。

  6. 选择“添加证书或机密”以设置应用的凭据。

  7. 证书 & 机密 页上,选择 + 新建客户端密码

  8. 在打开的“添加客户端机密”打开的弹出面板中:

    • 对于 “说明”,请输入一个值 Current
    • 对于“过期”值,请保留默认值 。180 days
    • 选择“添加”以添加机密
  9. 证书 & 密钥 页上,复制客户端密钥的 Value 属性,以便在将来的步骤中使用。

    注释

    创建应用注册后,客户端机密值仅显示一次。 无需使此客户端密码失效即可添加更多客户端机密,但无法再次显示此值。

将角色分配给应用程序服务主体

接下来,确定应用在哪些资源上需要哪些角色(权限),并将这些角色分配给您创建的服务主体。 可以在资源、资源组或订阅范围分配角色。 此示例演示如何在资源组范围内分配角色,因为大多数应用将其所有 Azure 资源分组到单个资源组中。

  1. 在 Azure 门户中,导航到包含应用的资源组的 “概述 ”页。

  2. 在左侧导航栏中,选择“访问控制(IAM)”。

  3. “访问控制”(IAM) 页上,选择“ + 添加 ”,然后从下拉菜单中选择 “添加角色分配 ”。 “添加角色分配”页提供了多个选项卡来配置和分配角色。

  4. 在“ 角色 ”选项卡上,使用搜索框查找要分配的角色。 选择角色,然后选择“ 下一步”。

  5. 在“ 成员 ”选项卡上:

    • 对于 “分配对值的访问权限 ”,请选择“ 用户”、“组”或服务主体
    • 对于 “成员 ”值,选择 “+ 选择成员 ”以打开 “选择成员 ”浮出控件面板。
    • 搜索之前创建的服务主体,并从筛选的结果中选择它。 选择 “选择” 以选择组并关闭浮动面板。
    • 选择“成员”选项卡底部的“审阅 + 分配”。

    一个屏幕截图,显示如何将角色分配给服务主体。

  6. 在“ 审阅 + 分配 ”选项卡上,选择页面底部的 “审阅 + 分配 ”。

设置应用环境变量

在运行时,来自 Azure 标识库的某些凭据(例如 DefaultAzureCredential EnvironmentCredentialClientSecretCredential)按约定在环境变量中搜索服务主体信息。 使用 JavaScript 时,有多种方法可以配置环境变量,具体取决于工具和环境。

无论选择哪种方法,都为服务主体配置以下环境变量:

  • AZURE_CLIENT_ID:用于标识 Azure 中注册的应用。
  • AZURE_TENANT_ID:Microsoft Entra 租户的 ID。
  • AZURE_CLIENT_SECRET:为应用生成的机密凭据。

在 Visual Studio Code 中,可以在项目的 launch.json 文件中设置环境变量。 应用启动时会自动拉取这些值。 但是,这些配置不会在部署期间与应用一起运行,因此需要在目标托管环境中设置环境变量。

"configurations": [
{
    "env": {
        "NODE_ENV": "development",
        "AZURE_CLIENT_ID": "<your-client-id>",
        "AZURE_TENANT_ID":"<your-tenant-id>",
        "AZURE_CLIENT_SECRET": "<your-client-secret>"
    }
}

从应用向 Azure 服务进行身份验证

Azure 标识库提供各种凭据-适用于支持不同方案和Microsoft Entra 身份验证流的实现TokenCredential。 前面的步骤演示如何在本地和生产环境中使用服务主体时使用 ClientSecretCredential

实现代码

在 Node.js 项目中添加 @azure/标识 包:

npm install @azure/identity

Azure 服务使用各种 Azure SDK 客户端库中的专用客户端类进行访问。 对于在应用中创建 Azure SDK 客户端对象的任何 JavaScript 代码,请执行以下步骤:

  1. ClientSecretCredential 模块中导入 @azure/identity 类。
  2. 使用 tenantIdclientIdclientSecret 创建 ClientSecretCredential 对象。
  3. ClientSecretCredential 实例传递给 Azure SDK 客户端对象构造函数。

以下代码段显示了此方法的示例:

import { BlobServiceClient } from '@azure/storage-blob';
import { ClientSecretCredential } from '@azure/identity';

// Authentication
const tenantId = process.env.AZURE_TENANT_ID;
const clientId = process.env.AZURE_CLIENT_ID;
const clientSecret = process.env.AZURE_CLIENT_SECRET;

// Azure Storage account name
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;

if (!tenantId || !clientId || !clientSecret || !accountName) {
  throw Error('Required environment variables not found');
}

const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);

const blobServiceClient = new BlobServiceClient(
  `https://${accountName}.blob.core.windows.net`,
  credential
);

另一种方法是将 ClientSecretCredential 对象直接传递到 Azure SDK 客户端构造函数:

const blobServiceClient = new BlobServiceClient(
  `https://${accountName}.blob.core.windows.net`,
  new ClientSecretCredential(tenantId, clientId, clientSecret)
);