托管在Azure外部的应用(如本地或第三方数据中心)应通过 Microsoft Entra ID 使用应用程序服务主体对Azure服务进行身份验证。 在以下部分中,你将了解:
- 如何使用 Microsoft Entra注册应用程序以创建服务主体。
- 如何为角色分配范围权限。
- 如何通过应用代码使用服务主体进行身份验证。
通过使用专用应用程序服务主体,可以在访问Azure资源时遵循最低特权原则。 限制在开发过程中应用的特定要求的权限,以防止意外访问适用于其他应用或服务的Azure资源。 此方法还有助于避免在将应用移动到生产环境时出现的问题,方法是确保应用在开发环境中没有超特权。
为每个托管应用的环境创建不同的应用注册。 可以为每个服务主体配置特定于环境的资源权限,并确保部署到一个环境的应用无法访问另一个环境中的Azure资源。
在 Azure 中注册应用
使用Azure门户或Azure CLI通过Azure中的应用注册创建应用程序服务主体对象。
在Azure门户中,使用搜索栏导航到 App registrations 页。
在 App registrations 页上,选择“+ 新建注册。
在“注册应用程序”页面上:
- 对于 名称 字段,请输入包含应用名称和目标环境的描述性值。
- 对于支持的帐户类型,请仅选择此组织目录中的帐户(仅限 Microsoft 客户引导 - 单租户),或选择最能满足你的要求的选项。
选择 注册 以注册应用并创建服务主体。
在应用的 应用注册 页上,复制 应用程序(客户端)ID 和 目录(租户)ID 并将其粘贴到临时位置,以便在应用代码配置中稍后使用。
选择“添加证书或机密”以设置应用的凭据。
在 证书 & 机密 页上,选择 + 新建客户端密码。
在打开的“添加客户端机密”打开的弹出面板中:
- 对于 “说明”,请输入一个值
Current。 - 对于“过期”值,请保留默认值 。
180 days - 选择“”,然后选择“”以添加密钥。
- 对于 “说明”,请输入一个值
在 证书 & 密钥 页上,复制客户端密钥的 Value 属性,以便在将来的步骤中使用。
注释
创建应用注册后,客户端机密值仅显示一次。 无需使此客户端密码失效即可添加更多客户端机密,但无法再次显示此值。
将角色分配给应用程序服务主体
接下来,确定应用在哪些资源上需要哪些角色(权限),并将这些角色分配给您创建的服务主体。 可以在资源、资源组或订阅范围分配角色。 此示例演示如何在资源组范围内分配角色,因为大多数应用将所有Azure资源分组到单个资源组中。
在 Azure 门户中,导航到包含应用的资源组的 Overview 页。
在左侧导航栏中,选择“访问控制(IAM)”。
在 “访问控制”(IAM) 页上,选择“ + 添加 ”,然后从下拉菜单中选择 “添加角色分配 ”。 “添加角色分配”页提供了多个选项卡来配置和分配角色。
在“ 角色 ”选项卡上,使用搜索框查找要分配的角色。 选择角色,然后选择“ 下一步”。
在“ 成员 ”选项卡上:
- 对于 “分配对值的访问权限 ”,请选择“ 用户”、“组”或服务主体 。
- 对于 “成员 ”值,选择 “+ 选择成员 ”以打开 “选择成员 ”浮出控件面板。
- 搜索之前创建的服务主体,并从筛选的结果中选择它。 选择 “选择” 以选择组并关闭浮动面板。
- 选择“成员”选项卡底部的“审阅 + 分配”。
在“ 审阅 + 分配 ”选项卡上,选择页面底部的 “审阅 + 分配 ”。
设置应用环境变量
在运行时,来自 Azure 标识库的某些凭据(例如 DefaultAzureCredential、EnvironmentCredential 和 ClientSecretCredential)按环境变量中的约定搜索服务主体信息。 使用Java时,可以根据工具和环境以多种方式配置环境变量。
无论选择哪种方法,都为服务主体配置以下环境变量:
-
AZURE_CLIENT_ID:用于标识Azure中注册的应用。 -
AZURE_TENANT_ID:Microsoft Entra 租户的 ID。 -
AZURE_CLIENT_SECRET:为应用生成的机密凭据。
设置以下环境变量。 将占位符值替换为应用注册中的实际值:
export AZURE_CLIENT_ID="<your-client-id>"
export AZURE_TENANT_ID="<your-tenant-id>"
export AZURE_CLIENT_SECRET="<your-client-secret>"
对于在生产服务器上作为系统服务运行的Java应用程序,请在文件中定义环境变量,并在服务单元文件中使用 EnvironmentFile 指令引用它:
[Unit]
Description=Java application service
After=network.target
[Service]
User=app-user
WorkingDirectory=/path/to/java-app
EnvironmentFile=/path/to/java-app/app-environment-variables
ExecStart=/usr/bin/java -jar app.jar
[Install]
WantedBy=multi-user.target
环境文件应包含具有其值的环境变量列表:
AZURE_CLIENT_ID=<your-client-id>
AZURE_TENANT_ID=<your-tenant-id>
AZURE_CLIENT_SECRET=<your-client-secret>
通过应用向Azure服务进行身份验证
Azure标识库提供了各种凭据—这是TokenCredential 的实现,支持不同的方案和Microsoft Entra身份验证流程。 以下步骤演示了在本地和生产环境中与服务主体一起使用ClientSecretCredential的方法。
实现代码
将 azure-identity 依赖项添加到 pom.xml 文件:
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-identity</artifactId>
</dependency>
可以使用来自各种Azure SDK客户端库的专用客户端类来访问Azure服务。 对于在应用中创建Azure SDK客户端对象的任何Java代码,请执行以下步骤:
- 从
com.azure.identity包导入ClientSecretCredentialBuilder类。 - 通过使用
ClientSecretCredentialBuilder、tenantId、clientId和clientSecret创建ClientSecretCredential对象。 - 将
ClientSecretCredential实例传递给Azure SDK客户端对象生成器的credential方法。
以下代码段显示了此方法的示例:
import com.azure.identity.ClientSecretCredential;
import com.azure.identity.ClientSecretCredentialBuilder;
import com.azure.storage.blob.BlobServiceClient;
import com.azure.storage.blob.BlobServiceClientBuilder;
String tenantId = System.getenv("AZURE_TENANT_ID");
String clientId = System.getenv("AZURE_CLIENT_ID");
String clientSecret = System.getenv("AZURE_CLIENT_SECRET");
ClientSecretCredential credential = new ClientSecretCredentialBuilder()
.tenantId(tenantId)
.clientId(clientId)
.clientSecret(clientSecret)
.build();
BlobServiceClient blobServiceClient = new BlobServiceClientBuilder()
.endpoint("https://<account-name>.blob.core.windows.net")
.credential(credential)
.buildClient();