You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spring Boot启动时将Azure KeyVault属性加载到PropertySource

Spring Boot启动时加载Azure KeyVault属性到高优先级PropertySources解决方案

1. 添加必要依赖

直接引入Spring Cloud Azure KeyVault Starter和Jasypt Starter,保证版本兼容:

<!-- Maven 依赖 -->
<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter-keyvault-secrets</artifactId>
    <version>4.12.0</version> <!-- 替换为最新稳定版 -->
</dependency>
<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>3.0.5</version>
</dependency>

2. 清晰配置凭证与优先级

不用依赖自动配置的隐式逻辑,直接在配置文件里明确KeyVault连接信息和优先级,数值越小优先级越高(确保覆盖本地配置):

# application.yaml
spring:
  cloud:
    azure:
      keyvault:
        secrets:
          property-sources:
            - name: my-keyvault
              vault-url: https://你的密钥库名称.vault.azure.net/
              credential:
                client-id: ${AZURE_CLIENT_ID} # 从环境变量读取,避免硬编码
                client-secret: ${AZURE_CLIENT_SECRET}
                tenant-id: ${AZURE_TENANT_ID}
              enabled: true
              priority: 0 # 设为0,确保优先级高于本地配置文件

3. 自定义加载逻辑(官方Starter不满足时用)

如果官方Starter的自动配置不符合需求,自己实现EnvironmentPostProcessor,手动加载KeyVault属性并放到最前面:

编写处理器类

import com.azure.identity.ClientSecretCredential;
import com.azure.identity.ClientSecretCredentialBuilder;
import com.azure.security.keyvault.secrets.SecretClient;
import com.azure.security.keyvault.secrets.SecretClientBuilder;
import com.azure.security.keyvault.secrets.models.KeyVaultSecret;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;

import java.util.HashMap;
import java.util.Map;

public class AzureKeyVaultEnvironmentPostProcessor implements EnvironmentPostProcessor {

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        // 从环境变量/本地配置读取凭证参数
        String clientId = environment.getProperty("azure.client.id");
        String clientSecret = environment.getProperty("azure.client.secret");
        String tenantId = environment.getProperty("azure.tenant.id");
        String vaultUrl = environment.getProperty("azure.keyvault.url");

        // 创建凭证与密钥客户端
        ClientSecretCredential credential = new ClientSecretCredentialBuilder()
                .clientId(clientId)
                .clientSecret(clientSecret)
                .tenantId(tenantId)
                .build();

        SecretClient secretClient = new SecretClientBuilder()
                .vaultUrl(vaultUrl)
                .credential(credential)
                .build();

        // 加载所有密钥到Map
        Map<String, Object> keyVaultProps = new HashMap<>();
        secretClient.listPropertiesOfSecrets().forEach(secretProp -> {
            KeyVaultSecret secret = secretClient.getSecret(secretProp.getName());
            keyVaultProps.put(secret.getName(), secret.getValue());
        });

        // 将KeyVault属性放到最高优先级的PropertySource
        environment.getPropertySources().addFirst(new MapPropertySource("azure-keyvault-props", keyVaultProps));
    }
}

注册处理器

在src/main/resources/META-INF/spring.factories里添加:

org.springframework.boot.env.EnvironmentPostProcessor=你的包路径.AzureKeyVaultEnvironmentPostProcessor

4. 兼容Jasypt解密

如果KeyVault中存储的是ENC()格式的加密值,无需额外配置——Jasypt的环境处理器会自动解密所有PropertySource中的加密属性,只要你的KeyVault PropertySource优先级正确,解密逻辑会自动覆盖本地配置。

5. 验证优先级

启动应用后,可通过接口打印PropertySource顺序,确认KeyVault属性排在最前面:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PropCheckController {

    @Autowired
    private ConfigurableEnvironment env;

    @GetMapping("/prop-sources")
    public String listPropSources() {
        StringBuilder sb = new StringBuilder();
        for (PropertySource<?> source : env.getPropertySources()) {
            sb.append(source.getName()).append(" - ").append(source.getClass().getName()).append("<br>");
        }
        return sb.toString();
    }
}

内容的提问来源于stack exchange,提问作者Mike Rother

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 12:45:20