使用 Azure Key Vault 证书在 Spring Boot 中启用 HTTPS
本教程介绍如何使用 Azure 密钥保管库和 Azure 资源的托管标识,使用 TLS/SSL 证书保护 Spring Boot(包括 Azure Spring Apps)应用。
生产级 Spring Boot 应用程序(无论是在云中还是本地)需要使用标准 TLS 协议对网络流量进行端到端加密。 你遇到的大多数 TLS/SSL 证书可从公共根证书颁发机构 (CA) 发现。 但是,有时这种发现是不可能的。 当无法发现证书时,应用必须有某种方法来加载此类证书,将其呈现给入站网络连接,并从出站网络连接接受它们。
Spring Boot 应用通常通过安装证书来启用 TLS。 证书安装到运行 Spring Boot 应用的 JVM 的本地密钥存储中。 使用 Azure 上的 Spring 时,不会在本地安装证书。 相反,适用于 Microsoft Azure 的 Spring 集成提供了一种安全且顺畅的方式,用于在 Azure 密钥保管库和 Azure 资源的托管标识的帮助下启用 TLS。
重要
目前,Spring Cloud Azure 证书初学者版本 4.x 或更高版本不支持 TLS/mTLS,它们仅自动配置密钥保管库证书客户端。 因此,如果要使用 TLS/mTLS,则无法迁移到版本 4.x。
先决条件
Azure 订阅 - 免费创建订阅。
受支持的 Java 开发工具包 (JDK) 版本 11。
Apache Maven 3.0 或更高版本。
用来测试功能的 cURL 或类似的 HTTP 实用工具。
Azure Windows 虚拟机 (VM) 实例。 如果没有,请使用 az vm create 命令和 UbuntuServer 提供的 Ubuntu 映像创建启用了了系统分配的托管标识的 VM 实例。 授予
Contributor
角色到系统分配的受管身份,然后将访问权限设置为scope
到您的订阅。一个 Azure 密钥保管库实例。 如果没有,请参阅快速入门:使用 Azure 门户创建密钥保管库。
Spring Boot 应用程序。 如果没有,请使用 Spring Initializr 创建一个 Maven 项目。 请务必选择 Maven 项目,并在依赖项下添加 Spring Web 依赖项,然后选择 Java 版本 8 或更高版本。
重要
要完成本文中的步骤,需要 Spring Boot 版本 2.5 或更高版本。
设置自签名 TLS/SSL 证书
本教程中的步骤适用于直接存储在 Azure 密钥保管库中的任何 TLS/SSL 证书(包括自签名证书)。 自签名证书不适合在生产环境中使用,但对于开发和测试应用程序非常有用。
本教程使用自签名证书。 要设置证书,请参阅快速入门:使用 Azure 门户在 Azure 密钥保管库中设置和检索证书。
注意
设置证书后,按照分配密钥保管库访问策略中的说明授予 VM 对密钥保管库的访问权限。
通过 TLS/SSL 证书保护连接
现在已有一个 VM 和一个密钥保管库实例,并已授予 VM 对密钥保管库的访问权限。 以下部分介绍如何在 Spring Boot 应用程序中通过 Azure 密钥保管库中的 TLS/SSL 证书安全地连接。 本教程演示以下两种方案:
- 运行具有安全入站连接的 Spring Boot 应用程序
- 运行具有安全出站连接的 Spring Boot 应用程序
提示
在以下步骤中,代码将打包成可执行文件,并上传到 VM。 不要忘记在 VM 中安装 OpenJDK。
运行具有安全入站连接的 Spring Boot 应用程序
当入站连接的 TLS/SSL 证书来自 Azure 密钥保管库时,请按照以下步骤配置应用程序:
将以下依赖项添加到 pom.xml 文件:
<dependency> <groupId>com.azure.spring</groupId> <artifactId>azure-spring-boot-starter-keyvault-certificates</artifactId> <version>3.14.0</version> </dependency>
在 application.properties 配置文件中配置密钥保管库凭据。
server.ssl.key-alias=<the name of the certificate in Azure Key Vault to use> server.ssl.key-store-type=AzureKeyVault server.ssl.trust-store-type=AzureKeyVault server.port=8443 azure.keyvault.uri=<the URI of the Azure Key Vault to use>
这些值使 Spring Boot 应用能够针对 TLS/SSL 证书执行加载操作,如本教程开头所述。 下表对这些属性值进行了说明。
properties 说明 server.ssl.key-alias
的值 --name
参数的az keyvault certificate create
.server.ssl.key-store-type
必须是 AzureKeyVault
。server.ssl.trust-store-type
必须是 AzureKeyVault
。server.port
用于监听 HTTPS 连接的本地 TCP 端口。 azure.keyvault.uri
的 vaultUri
属性中的az keyvault create
. 将该值保存在环境变量中。密钥保管库的唯一特定属性是
azure.keyvault.uri
. 应用程序在具有系统分配的托管标识,并已被授予密钥库访问权限的虚拟机上运行。 因此,应用也被授予访问权限。这些更改使 Spring Boot 应用能够加载 TLS/SSL 证书。 在下一步中,你将启用应用对 TLS/SSL 证书执行接受操作,如本教程开头所述。
编辑启动类文件,使其包含以下内容。
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication @RestController public class SsltestApplication { public static void main(String[] args) { SpringApplication.run(SsltestApplication.class, args); } @GetMapping(value = "/ssl-test") public String inbound(){ return "Inbound TLS is working!!"; } @GetMapping(value = "/exit") public void exit() { System.exit(0); } }
从未经身份验证的 REST GET 调用中调用
System.exit(0)
仅用于演示目的。 请勿在实际应用程序中使用System.exit(0)
。这段代码说明了 礼品 本教程开头提到的操作。 以下列表突出显示了有关此代码的一些详细信息:
- 现在有一个
@RestController
上的SsltestApplication
类由 Spring Initializr 生成。 - 有一个用
@GetMapping
注释的方法,其中value
用于你发出的 HTTP 调用。 - 当浏览器向
/ssl-test
路径发出 HTTPS 请求时,inbound
方法只会返回问候语。inbound
方法说明了服务器如何向浏览器提供 TLS/SSL 证书。 - 当调用时,
exit
方法会导致 JVM 退出。 这种方法便于在本教程的上下文中轻松运行样例。
- 现在有一个
运行以下命令以编译代码并将其打包成可执行的 JAR 文件中。
mvn clean package
验证在
<your-resource-group-name>
允许从您的 IP 地址通过端口 22 和 8443 输入流量。 若要了解如何配置网络安全组规则以允许入站流量,请参阅 创建、更改或删除网络安全组中的 使用安全规则 部分。将可执行 JAR 文件放在 VM 上。
cd target sftp azureuser@<your VM public IP address> put *.jar
现在你已经构建了 Spring Boot 应用并将其上传到 VM,请使用以下步骤在 VM 上运行它,并使用
curl
调用 REST 终结点。使用 SSH 连接到 VM,然后运行可执行的 JAR。
set -o noglob ssh azureuser@<your VM public IP address> "java -jar *.jar"
打开一个新的 Bash shell 并执行以下命令,以验证服务器是否提供 TLS/SSL 证书。
curl --insecure https://<your VM public IP address>:8443/ssl-test
调用
exit
路径来杀死服务器并关闭网络套接字。curl --insecure https://<your VM public IP address>:8443/exit
现在你已经看到了 负荷 和 礼品 使用自签名的 TLS/SSL 证书进行操作,对应用程序做一些微不足道的更改,以查看 接受 行动。
运行具有安全出站连接的 Spring Boot 应用程序
在本部分中,将修改上一部分中的代码,以便出站连接的 TLS/SSL 证书来自 Azure 密钥保管库。 因此,在 负荷, 礼品, 和 accept Azure 密钥库满足这些要求。
将 Apache HTTP 客户端依赖项添加到 pom.xml 文件:
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency>
添加一个名为
ssl-test-outbound
. 此终结点为其自身打开一个 TLS 套接字,并验证 TLS 连接是否接受 TLS/SSL 证书。 用以下代码替换启动类的前一部分。import java.security.KeyStore; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import com.azure.security.keyvault.jca.KeyVaultLoadStoreParameter; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.TrustSelfSignedStrategy; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.ssl.SSLContexts; @SpringBootApplication @RestController public class SsltestApplication { public static void main(String[] args) { SpringApplication.run(SsltestApplication.class, args); } @GetMapping(value = "/ssl-test") public String inbound(){ return "Inbound TLS is working!!"; } @GetMapping(value = "/ssl-test-outbound") public String outbound() throws Exception { KeyStore azureKeyVaultKeyStore = KeyStore.getInstance("AzureKeyVault"); KeyVaultLoadStoreParameter parameter = new KeyVaultLoadStoreParameter( System.getProperty("azure.keyvault.uri")); azureKeyVaultKeyStore.load(parameter); SSLContext sslContext = SSLContexts.custom() .loadTrustMaterial(azureKeyVaultKeyStore, null) .build(); HostnameVerifier allowAll = (String hostName, SSLSession session) -> true; SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, allowAll); CloseableHttpClient httpClient = HttpClients.custom() .setSSLSocketFactory(csf) .build(); HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); requestFactory.setHttpClient(httpClient); RestTemplate restTemplate = new RestTemplate(requestFactory); String sslTest = "https://localhost:8443/ssl-test"; ResponseEntity<String> response = restTemplate.getForEntity(sslTest, String.class); return "Outbound TLS " + (response.getStatusCode() == HttpStatus.OK ? "is" : "is not") + " Working!!"; } @GetMapping(value = "/exit") public void exit() { System.exit(0); } }
运行以下命令以编译代码并将其打包成可执行的 JAR 文件中。
mvn clean package
使用本文前面提到的相同的
sftp
命令再次上传应用。cd target sftp <your VM public IP address> put *.jar
在 VM 上运行应用。
set -o noglob ssh azureuser@<your VM public IP address> "java -jar *.jar"
服务器运行后,验证服务器是否接受 TLS/SSL 证书。 在发出前一个
curl
命令的 Bash shell 中,运行以下命令。curl --insecure https://<your VM public IP address>:8443/ssl-test-outbound
应该看到消息
Outbound TLS is working!!
。调用
exit
路径来杀死服务器并关闭网络套接字。curl --insecure https://<your VM public IP address>:8443/exit
您现在已经看到了一个简单的示例 负荷, 礼品, 和 接受 使用存储在 Azure 密钥库中的自签名 TLS/SSL 证书进行操作。
部署到 Azure Spring Apps
现在,你已在本地运行 Spring Boot 应用程序,是时候将其转移到生产环境了。 借助 Azure Spring Apps,可以轻松地将 Spring Boot 应用程序部署到 Azure,不需更改任何代码。 该服务管理 Spring 应用程序的基础结构,让开发人员可以专注于代码。 Azure Spring Apps 可以通过以下方法提供生命周期管理:综合性监视和诊断、配置管理、服务发现、CI/CD 集成、蓝绿部署等。 若要将应用程序部署到 Azure Spring Apps,请参阅在 Azure Spring Apps 中部署你的第一个应用程序。
后续步骤
若要了解有关 Spring 和 Azure 的详细信息,请继续访问“Azure 上的 Spring”文档中心。