在Spring Boot中使用HTTPS

         
banq
18-07-19 63 1

在本文中,我们将学习在Spring Boot中使用自签名证书配置SSL(HTTPS),并且要在嵌入式Tomcat上启用Spring Boot应用程序的SSL,我们需要学习以下步骤:


1.创建SSL证书:生成自签名证书,或者使用由受信任的证书颁发机构(CA)颁发的证书。

2.在Spring Boot中启用HTTPS:这可以通过Spring Boot 项目中的一些简单配置来完成。

3. 将HTTP重定向到HTTPS :在某些情况下,最好也能从HTTP访问你的应用,将所有HTTP流量重定向到HTTPS端点。
我们可以使用自己签名的证书进行开发和测试。在生产中,应该使用由可信证书颁发机构(CA)颁发的证书。否则,它将向用户显示不受信任的警告。

生成自签名SSL证书
每个Java Runtime Environment (JRE) 都捆绑了一个名为keytool的证书管理实用程序 。这可用于生成自签名证书。两种最常用的格式是:

1.对于keystores是采用JKS,这是特定于Java的专有格式。
2.PKCS12行业标准格式。

JKS曾经是默认选择,但现在Oracle建议采用PKCS12这种格式。

打开终端提示并编写以下命令以创建JKS keystore :


keytool -genkeypair -alias https-integration -keyalg RSA -keysize 2048 -keystore ./keystore.jks -validity 3650


要创建PKCS12 keystore,请使用以下命令:

keytool -genkeypair -alias https-integration -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore ./keystore.p12 -validity 3650

keystore的密码必须至少有6个字符。


我们需要提供一些输入信息,但可以跳过所有这些信息(只需按 Enter 跳过一个选项)。在名字和姓氏的位置,我们可能想要插入主机的基本名称localhost。这可能很重要,因为SSL证书应该具有正确的CN.公用名(CN)/公用名(CN),应该对接收证书的Web服务器进行完全限定域名,否则,我们可以得到错误SSL Exception CertificateException:找不到与您的域名 匹配的名称,请检查此异常的详细信息。

操作结束后会在当前目录下获得一个keystore,包含全新SSL证书的内容,比如keystore.jks。要检查JKS 密钥库的内容,可以再次使用keytool:

keytool -list


在Gateway项目中启用HTTPS:

我们现在可以设置 Spring Boot Project 使用该证书接受请求 HTTPS 而不是 HTTP 。首先要做的是将生成的文件比如keystore.jks置于Spring Boot项目内部。我们可以将它放在 resources 文件夹中或里面root folder。现在我们需要将以下配置放入下面任一其中 application.properties file / application.yaml / bootstrap.yml file。


spring::
application::
name: spring-test-service: spring-test-service

# SSL Configurations STARTS Here# SSL Configurations STARTS Here
server::
port: 8443: 8443
http-port: 8099-port: 8099
ssl::
key-store: classpath:keystore.p12-store: classpath:keystore.p12
key-store-password: -store-password: test@123
keyStoreType: PKCS12: PKCS12
keyAlias: https-integration: https-integration
# SSL Configurations ENDS Here# SSL Configurations ENDS Here

logging::
level::
org.springframework: INFO.springframework: INFO
com.qualys: INFO.qualys: INFO
pattern::
console: "%d{yyyy-MM-dd HH:mm:ss} - %msg%n": "%d{yyyy-MM-dd HH:mm:ss} - %msg%n"
file:
"%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n": "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
file: /tmp/logs/https-integration-application.log: /tmp/logs/https-integration-application.log


我们使用server.port 属性指定自定义端口 (默认情况下为8080)。如果我们在类路径中有Spring Security,那么我们应该将 security.require-ssl 属性设置true, 这是为自动阻止来自HTTP的任何请求,而不显式触及任何Spring Security配置类。

1.配置中server.ssl.key-store-type 属性定义了 keystore使用格式 :是 JKS 或 PKCS12
2.server.ssl.key-store 属性指定keystore 文件的位置:可以是keystore.jks或 keystore.p12。在这里,我们希望Spring在classpath下寻找这两个文件中一个。


将HTTP请求重定向到HTTPS
在某些情况下,最好也让你的应用可访问HTTP,但将所有HTTP流量重定向到HTTPS。为实现这一目标,我们需要添加第二个Tomcat连接器,我们使用 @Configuration 类。


@Slf4j
@Configuration
public class TomcatEmbed extends SpringServletContainerInitializer {

@Value("${server.port}")
private Integer httpsPort;

@Value(
"${server.http-port}")
private Integer httpPort;

@Bean
public TomcatServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat =
new TomcatServletWebServerFactory() {
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint(
"CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern(
"/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(initiateHttpConnector());
return tomcat;
}

private Connector initiateHttpConnector() {
Connector connector =
new Connector(
"org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme(
"http");
connector.setPort(httpPort);
connector.setSecure(false);
connector.setRedirectPort(httpsPort);
return connector;
}

/**
* The following code is required only if you WebSocket endpoint
* in your application. We added it for some later example. You
* can omit this part if you don't have any WebSocket endpoint.
*/

@Bean
public TomcatContextCustomizer tomcatContextCustomizer() {
log.info(
"TOMCAT CONTEXT CUSTOMIZER INITIALIZED");
return new TomcatContextCustomizer() {
@Override
public void customize(Context context) {
context.addServletContainerInitializer(new WsSci(), null);
}
};
}
}



将SSL证书分发给客户

由于我们使用的是自签名SSL证书,因此浏览器不会信任我们的应用程序,并会警告用户它不是安全域。这对所有客户浏览器来说都是一样的。通过向客户提供证书,可以让客户信任该应用程序。由于我们将证书存储在keystore中,我们需要通过 keytool for JKS格式提取它:


keytool -export -keystore keystore.jks -alias tomcat -file myCertificate.crt
-export -keystore keystore.jks -alias tomcat -file myCertificate.crt


现在,keytool将要求输入keystore密码,在本指南开头设置的 过密码。现在我们可以将证书导入客户端。在下一步中, 在JRE密钥库中导入证书,我们将解释如何将JKS 格式证书导入到JRE。

另一方面,如果我们使用keystore的PKCS12格式,我们应该可以直接使用它而无需提取证书。请自行搜索有关 如何将PKCS12文件导入浏览器的指南。如果您已启用 macOS,则可以直接将证书导入 Keychain Access (Safari,Chrome和Opera等浏览器用于管理证书)。

如果我们要部署应用到localhost,我们可能需要从浏览器中再做一步:激活localhost启用不安全的连接。在Chrome中,我们可以通过在搜索栏中编写以下网址来执行此操作: chrome://flags/#allow-insecure-localhost 并激活相应选项。

在JRE密钥库中导入证书
为了使 JRE 信任我们的证书,我们需要导入它到 cacerts里面: JRE keystore 负责持有证书。从终端输入命令(我们需要以管理员权限运行终端):


keytool -importcert -file myCertificate.crt -alias tomcat -keystore -importcert -file myCertificate.crt -alias tomcat -keystore
C:/Program\Files/Java/jdk1.8.0_121/jre/lib/security/cacerts:/Program\ Files/Java/jdk1.8.0_121/jre/lib/security/cacerts


上述命令执行时会要求输入JRE keystore密码,最后, keytool 会询问我们是否要信任此证书?现在,我们可以看到证书已添加到密钥库中的消息。现在,应用程序可以同时接受HTTP和HTTPS请求。但是所有HTTP呼叫都将被重定向到 HTTPS端点。

从这里下载源代码: GITHUB

Spring Boot SSL [https] Integration | Spring Conce
[该贴被banq于2018-07-19 21:31修改过]

1