在Kotlin/SpringBoot中从Azure KeyVault加载证书到密钥库用于请求
问题描述
我的后端API请求需要证书验证,当前是从代码仓库里的.p12文件加载证书初始化WebClient,代码如下:
private fun getWebClient(): WebClient { val ks: KeyStore = KeyStore.getInstance("PKCS12") ks.load(ClassPathResource("keystore.p12").inputStream, config.trustStorePassword.toCharArray()) val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()) kmf.init(ks, config.trustStorePassword.toCharArray()) val sslContext = SslContextBuilder .forClient() .keyManager(kmf) .build() val httpClient: HttpClient = HttpClient.create().secure { sslSpec -> sslSpec.sslContext(sslContext) } return WebClient .builder() .baseUrl(config.BaseUrl) .clientConnector(ReactorClientHttpConnector(httpClient)) .build() }
现在服务部署到Azure AppService,想改成从Azure KeyVault加载证书,已完成KeyVault创建、证书导入,且通过托管身份给AppService授权了访问权限。
使用Spring Boot 2.7.7,依赖如下:
implementation("com.azure.spring:spring-cloud-azure-starter:4.5.0") implementation("com.azure.spring:spring-cloud-azure-starter-keyvault:4.5.0")
参考文档时发现azure.keyvault.uri已废弃,改用spring.cloud.azure.keyvault.certificate.endpoint,但文档里的KeyVaultLoadStoreParameter类无法解析,不知道如何实现从KeyVault加载证书并配置WebClient。
解决方案
1. 调整依赖
KeyVaultLoadStoreParameter属于旧版Azure SDK实现,在spring-cloud-azure-starter 4.x版本中已不再使用,需改用Key Vault Certificates客户端库直接获取证书,更新依赖如下:
implementation("com.azure.spring:spring-cloud-azure-starter-keyvault-certificates:4.5.0") implementation("io.projectreactor.netty:reactor-netty-http")
2. 配置application.yml
添加Key Vault相关配置,依托托管身份完成认证:
spring: cloud: azure: keyvault: certificate: endpoint: <你的Key Vault URI> credential: managed-identity-client-id: <你的AppService托管身份客户端ID> # 系统托管身份可省略此配置
3. 实现证书加载与WebClient配置
通过AzureKeyVaultCertificateClient获取证书,转换为KeyStore后配置WebClient的SSL上下文:
import com.azure.security.keyvault.certificates.KeyVaultCertificateClient import com.azure.security.keyvault.certificates.models.KeyVaultCertificateWithPolicy import io.netty.handler.ssl.SslContextBuilder import org.springframework.web.reactive.function.client.WebClient import reactor.netty.http.client.HttpClient import java.security.KeyStore import java.security.cert.Certificate private fun getWebClient(certificateClient: KeyVaultCertificateClient, config: YourConfigClass): WebClient { // 从Key Vault获取目标证书(替换为你的证书名称) val certificate = certificateClient.getCertificate("your-certificate-name") val cert: Certificate = certificate.certificate // 创建临时KeyStore并加载证书 val ks: KeyStore = KeyStore.getInstance(KeyStore.getDefaultType()) ks.load(null, null) ks.setCertificateEntry("cert-alias", cert) // 初始化KeyManagerFactory val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()) kmf.init(ks, null) // 托管身份获取的证书无需密码 // 构建SSL上下文 val sslContext = SslContextBuilder .forClient() .keyManager(kmf) .build() // 配置HttpClient与WebClient val httpClient: HttpClient = HttpClient.create().secure { sslSpec -> sslSpec.sslContext(sslContext) } return WebClient .builder() .baseUrl(config.BaseUrl) .clientConnector(reactor.netty.http.client.ReactorClientHttpConnector(httpClient)) .build() }
4. 注入客户端实例
Spring Cloud Azure会自动配置AzureKeyVaultCertificateClient,直接在业务类中注入使用即可:
import org.springframework.stereotype.Component @Component class WebClientCreator( private val certificateClient: KeyVaultCertificateClient, private val config: YourConfigClass ) { fun create(): WebClient { return getWebClient(certificateClient, config) } }
关键说明
- 4.x版本的spring-cloud-azure-starter-keyvault-certificates不再使用
KeyVaultLoadStoreParameter,改为通过客户端库直接操作证书 - 托管身份会自动完成认证流程,无需在代码中配置密钥
- 确保AppService的托管身份拥有Key Vault的
Certificate Get权限
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐

