Azure Identity Java SDK

azure-identity-java
分类通用
作者Agentic Awesome Skills 社区
许可MIT
评分4.50/5
使用11.7K

Azure Identity (Java)

使用 Microsoft Entra ID (Azure AD) 为 Java 应用程序提供 Azure 服务的身份验证。

安装

xml
<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-identity</artifactId>
    <version>1.15.0</version>
</dependency>

核心概念

| 凭据 (Credential) | 使用场景 |
|------------|----------|
| DefaultAzureCredential | 推荐 - 适用于开发和生产环境 |
| ManagedIdentityCredential | Azure 托管应用 (App Service, Functions, VM) |
| EnvironmentCredential | 使用环境变量的 CI/CD 流水线 |
| ClientSecretCredential | 使用密钥的服务主体 (Service Principal) |
| ClientCertificateCredential | 使用证书的服务主体 (Service Principal) |
| AzureCliCredential | 使用 az login 的本地开发 |
| InteractiveBrowserCredential | 交互式登录流程 |
| DeviceCodeCredential | 无头设备身份验证 |

DefaultAzureCredential (推荐)

DefaultAzureCredential 会按顺序尝试多种身份验证方法:

1. 环境变量
2. 工作负载标识 (Workload Identity)
3. 托管标识 (Managed Identity)
4. Azure CLI
5. Azure PowerShell
6. Azure Developer CLI

java
import com.azure.identity.DefaultAzureCredential;
import com.azure.identity.DefaultAzureCredentialBuilder;

// 简单用法
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();

// 与任何 Azure 客户端配合使用
BlobServiceClient blobClient = new BlobServiceClientBuilder()
.endpoint("https://<storage-account>.blob.core.windows.net")
.credential(credential)
.buildClient();

KeyClient keyClient = new KeyClientBuilder()
.vaultUrl("https://<vault-name>.vault.azure.net")
.credential(credential)
.buildClient();

配置 DefaultAzureCredential

java
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder()
    .managedIdentityClientId("<user-assigned-identity-client-id>")  // 用于用户分配的托管标识
    .tenantId("<tenant-id>")                                        // 限制在特定租户
    .excludeEnvironmentCredential()                                 // 跳过环境变量
    .excludeAzureCliCredential()                                    // 跳过 Azure CLI
    .build();

托管标识 (Managed Identity)

适用于 Azure 托管应用程序 (App Service, Functions, AKS, VM)。

java
import com.azure.identity.ManagedIdentityCredential;
import com.azure.identity.ManagedIdentityCredentialBuilder;

// 系统分配的托管标识
ManagedIdentityCredential credential = new ManagedIdentityCredentialBuilder()
.build();

// 用户分配的托管标识 (通过客户端 ID)
ManagedIdentityCredential credential = new ManagedIdentityCredentialBuilder()
.clientId("<user-assigned-client-id>")
.build();

// 用户分配的托管标识 (通过资源 ID)
ManagedIdentityCredential credential = new ManagedIdentityCredentialBuilder()
.resourceId("/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<name>")
.build();

使用密钥的服务主体

java
import com.azure.identity.ClientSecretCredential;
import com.azure.identity.ClientSecretCredentialBuilder;

ClientSecretCredential credential = new ClientSecretCredentialBuilder()
.tenantId("<tenant-id>")
.clientId("<client-id>")
.clientSecret("<client-secret>")
.b


uild();
code
## 使用证书的服务主体 (Service Principal)
java
import com.azure.identity.ClientCertificateCredential;
import com.azure.identity.ClientCertificateCredentialBuilder;

// 从 PEM 文件加载
ClientCertificateCredential credential = new ClientCertificateCredentialBuilder()
.tenantId("<tenant-id>")
.clientId("<client-id>")
.pemCertificate("<path-to-cert.pem>")
.build();

// 从带有密码的 PFX 文件加载
ClientCertificateCredential credential = new ClientCertificateCredentialBuilder()
.tenantId("<tenant-id>")
.clientId("<client-id>")
.pfxCertificate("<path-to-cert.pfx>", "<pfx-password>")
.build();

// 为 SNI 发送证书链
ClientCertificateCredential credential = new ClientCertificateCredentialBuilder()
.tenantId("<tenant-id>")
.clientId("<client-id>")
.pemCertificate("<path-to-cert.pem>")
.sendCertificateChain(true)
.build();

code
## 环境凭据 (Environment Credential)

从环境变量中读取凭据。

java
import com.azure.identity.EnvironmentCredential;
import com.azure.identity.EnvironmentCredentialBuilder;

EnvironmentCredential credential = new EnvironmentCredentialBuilder().build();

code
### 必需的环境变量

使用密钥的服务主体:

bash
AZURE_TENANT_ID=<tenant-id>
AZURE_CLIENT_ID=<client-id>
AZURE_CLIENT_SECRET=<client-secret>
code
使用证书的服务主体:
bash
AZURE_TENANT_ID=<tenant-id>
AZURE_CLIENT_ID=<client-id>
AZURE_CLIENT_CERTIFICATE_PATH=/path/to/cert.pem
AZURE_CLIENT_CERTIFICATE_PASSWORD=<optional-password>
code
使用用户名/密码:
bash
AZURE_TENANT_ID=<tenant-id>
AZURE_CLIENT_ID=<client-id>
AZURE_USERNAME=<username>
AZURE_PASSWORD=<password>
code
## Azure CLI 凭据

用于通过 az login 进行本地开发。

java
import com.azure.identity.AzureCliCredential;
import com.azure.identity.AzureCliCredentialBuilder;

AzureCliCredential credential = new AzureCliCredentialBuilder()
.tenantId("<tenant-id>") // 可选:指定租户
.build();

code
## 交互式浏览器 (Interactive Browser)

用于需要用户登录的桌面应用程序。

java
import com.azure.identity.InteractiveBrowserCredential;
import com.azure.identity.InteractiveBrowserCredentialBuilder;

InteractiveBrowserCredential credential = new InteractiveBrowserCredentialBuilder()
.clientId("<client-id>")
.redirectUrl("http://localhost:8080") // 必须与应用注册信息匹配
.build();

code
## 设备代码 (Device Code)

用于无头设备(如 IoT、CLI 工具)。

java
import com.azure.identity.DeviceCodeCredential;
import com.azure.identity.DeviceCodeCredentialBuilder;

DeviceCodeCredential credential = new DeviceCodeCredentialBuilder()
.clientId("<client-id>")
.challengeConsumer(challenge -> {
// 显示给用户
System.out.println(challenge.getMessage());
})
.build();

code
## 链式凭据 (Chained Credential)

创建自定义身份验证链。

java
import com.azure.identity.ChainedTokenCredential;
import com.azure.identity.ChainedTokenCredentialBuilder;

ChainedTokenCredential credential = new ChainedTokenCredentialBuilder()
.addFirst(new ManagedIdentityCredentialBuilder().build())
.addLast(new AzureCliCredentialBuilder().build())
.build();

code
## 工作负载身份 (Workload Identity - AKS)

用于启用工作负载身份的 Azure Kubernetes Service。

java
import com.azure.identity.WorkloadIdentityCredential;
import com.azure.identity.WorkloadIdentityCredentialBuilder;

// 从 AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_FEDERA 读取

code
TED_TOKEN_FILE
WorkloadIdentityCredential credential = new WorkloadIdentityCredentialBuilder().build();

// 或显式配置
WorkloadIdentityCredential credential = new WorkloadIdentityCredentialBuilder()
.tenantId("<tenant-id>")
.clientId("<client-id>")
.tokenFilePath("/var/run/secrets/azure/tokens/azure-identity-token")
.build();

令牌缓存

启用持久化令牌缓存以提升性能。

java
// 启用令牌缓存(默认在内存中)
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder()
    .enableAccountIdentifierLogging()
    .build();

// 使用共享令牌缓存(适用于多凭据场景)
SharedTokenCacheCredential credential = new SharedTokenCacheCredentialBuilder()
.clientId("<client-id>")
.build();

主权云 (Sovereign Clouds)

java
import com.azure.identity.AzureAuthorityHosts;

// Azure 政府云
DefaultAzureCredential govCredential = new DefaultAzureCredentialBuilder()
.authorityHost(AzureAuthorityHosts.AZURE_GOVERNMENT)
.build();

// Azure 中国云
DefaultAzureCredential chinaCredential = new DefaultAzureCredentialBuilder()
.authorityHost(AzureAuthorityHosts.AZURE_CHINA)
.build();

错误处理

java
import com.azure.identity.CredentialUnavailableException;
import com.azure.core.exception.ClientAuthenticationException;

try {
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
AccessToken token = credential.getToken(new TokenRequestContext()
.addScopes("https://management.azure.com/.default"));
} catch (CredentialUnavailableException e) {
// 无法找到可用于身份验证的凭据
System.out.println("Authentication failed: " + e.getMessage());
} catch (ClientAuthenticationException e) {
// 身份验证错误(凭据错误、已过期等)
System.out.println("Auth error: " + e.getMessage());
}

日志记录

启用身份验证日志以便调试。

java
// 通过环境变量
// AZURE_LOG_LEVEL=verbose

// 或通过代码实现
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder()
.enableAccountIdentifierLogging() // 记录账户信息
.build();

环境变量

bash
# DefaultAzureCredential 配置
AZURE_TENANT_ID=<tenant-id>
AZURE_CLIENT_ID=<client-id>
AZURE_CLIENT_SECRET=<client-secret>

托管身份 (Managed Identity)

AZURE_CLIENT_ID=<user-assigned-mi-client-id>

工作负载身份 (Workload Identity - AKS)

AZURE_FEDERATED_TOKEN_FILE=/var/run/secrets/azure/tokens/azure-identity-token

日志级别

AZURE_LOG_LEVEL=verbose

颁发机构主机 (Authority host)

AZURE_AUTHORITY_HOST=https://login.microsoftonline.com/

最佳实践

1. 使用 DefaultAzureCredential —— 实现从开发到生产环境的无缝切换。
2. 生产环境使用托管身份 —— 无需管理密钥,支持自动轮转。
3. 本地开发使用 Azure CLI —— 在运行应用前执行 az login
4. 最小权限原则 —— 仅向服务主体授予必要的权限。
5. 令牌缓存 —— 默认启用,可减少身份验证的往返请求。
6. 环境变量 —— 用于 CI/CD,避免在代码中硬编码密钥。

凭据选择矩阵

| 环境 | 推荐凭据 |
|-------------|----------------------|
| 本地开发 | DefaultAzureCredential (使用 Azure CLI) |
| Azure App Service | DefaultAzureCredential (使用托管身份) |
| Azure Functions | DefaultAzureCredential (使用托管身份) |
| Azure Kubernetes Service | WorkloadIdentityCredential |
| Azure 虚拟机 | DefaultAzureCredential (使用托管标识) |
| CI/CD 流水线 | EnvironmentCredential |
| 桌面应用 | InteractiveBrowserCredential |
| CLI 工具 | DeviceCodeCredential |

触发词

  • "Azure authentication Java", "DefaultAzureCredential Java"
  • "managed identity Java", "service principal Java"
  • "Azure login Java", "Azure credentials Java"
  • "AZURE_CLIENT_ID", "AZURE_TENANT_ID"

使用场景

本技能适用于执行概览中所描述的工作流或操作。

局限性

  • 仅在任务明确符合上述范围时使用此技能。
  • 不要将输出结果视为针对特定环境的验证、测试或专家评审的替代方案。
  • 如果缺少必要的输入、权限、安全边界或成功标准,请停止并请求澄清。