前提,我是在自己笔记本上做的。
1.申请SSL
进入到jdk安装目录的bin目录下,打开cmd命令窗口,执行以下命令:
keytool -genkey -alias https -keyalg RSA -keystore https.keystore
https
是我起的keystore的名字。别名alias也叫https。
按照提示做就可以,其实就是输入一些信息。
D:\jdk\jdk1.8.0_152\bin>keytool -genkey -alias https -keyalg RSA -keystore https.keystore
输入密钥库口令: -- 这里我用的是123456
再次输入新口令:
您的名字与姓氏是什么?
[Unknown]: zhang
您的组织单位名称是什么?
[Unknown]: zhang
您的组织名称是什么?
[Unknown]: zhang
您所在的城市或区域名称是什么?
[Unknown]: zhang
您所在的省/市/自治区名称是什么?
[Unknown]: zhang
该单位的双字母国家/地区代码是什么?
[Unknown]: zhang
CN=zhang, OU=zhang, O=zhang, L=zhang, ST=zhang, C=zhang是否正确?
[否]: 是
输入 <https> 的密钥口令
(如果和密钥库口令相同, 按回车):
再次输入新口令: -- 这里同样是输入123456
Warning:
JKS 密钥库使用专用格式。建议使用 "keytool -importkeystore -srckeystore https.keystore -destkeystore https.keystore -deststoretype pkcs12" 迁移到行业标准格式 PKCS12。
大家应该看到最后的警告信息了:JKS 密钥库使用专用格式。建议使用
"keytool -importkeystore -srckeystore https.keystore -destkeystore https.keystore -deststoretype pkcs12"
迁移到行业标准格式 PKCS12。
他给出的命令可以直接复制使用,粘贴到命令窗口。回车就行。
D:\jdk\jdk1.8.0_152\bin>keytool -importkeystore -srckeystore https.keystore -destkeystore https.keystore -deststoretype pkcs12
输入源密钥库口令: --还是123456
已成功导入别名 https 的条目。
已完成导入命令: 1 个条目成功导入, 0 个条目失败或取消
Warning:
已将 "https.keystore" 迁移到 Non JKS/JCEKS。将 JKS 密钥库作为 "https.keystore.old" 进行了备份。
完毕!然后就可以看到bin目录下有个文件。.old是头一个指令生成的,用的时候用不带old的那个。
2.项目配置
2.1keystore文件放在resource的根路径下
2.2配置yml文件
主要是增加了ssl相关的配置。
server:
port: 8089
ssl:
key-store: classpath:https.keystore # 路径
key-store-password: 123456 # 密码
keyStoreType: jks #类型
keyAlias: https # 别名
2.3修改pom文件
如果不改的话可能会报错Invalid keystore format
。
Caused by: java.lang.IllegalArgumentException: Invalid keystore format
at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:99)
at org.apache.tomcat.util.net.AbstractJsseEndpoint.initialiseSsl(AbstractJsseEndpoint.java:71)
at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:218)
at org.apache.tomcat.util.net.AbstractEndpoint.bindWithCleanup(AbstractEndpoint.java:1124)
at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:1137)
at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:574)
at org.apache.coyote.http11.AbstractHttp11Protocol.init(AbstractHttp11Protocol.java:74)
at org.apache.catalina.connector.Connector.initInternal(Connector.java:980)
... 21 common frames omitted
Caused by: java.io.IOException: Invalid keystore format
at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:658)
at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:56)
at sun.security.provider.KeyStoreDelegator.engineLoad(KeyStoreDelegator.java:224)
at sun.security.provider.JavaKeyStore$DualFormatJKS.engineLoad(JavaKeyStore.java:70)
at java.security.KeyStore.load(KeyStore.java:1445)
at org.apache.tomcat.util.security.KeyStoreUtil.load(KeyStoreUtil.java:69)
at org.apache.tomcat.util.net.SSLUtilBase.getStore(SSLUtilBase.java:217)
at org.apache.tomcat.util.net.SSLHostConfigCertificate.getCertificateKeystore(SSLHostConfigCertificate.java:206)
at org.apache.tomcat.util.net.SSLUtilBase.getKeyManagers(SSLUtilBase.java:280)
at org.apache.tomcat.util.net.SSLUtilBase.createSSLContext(SSLUtilBase.java:247)
at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:97)
... 28 common frames omitted
注意
<resources>
加的位置,在maven插件
的前面。
<build>
<finalName>${project.artifactId}</finalName>
<!--解决keystore文件解析报错 开始-->
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>https.keystore</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>https.keystore</include>
</includes>
</resource>
</resources>
<!--解决keystore文件解析报错 结束-->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
2.4增加配置类
启动主方法下面直接增加2个配置bean。有些地方我是写死的,应该从配置文件取,因为是演示,所以无所谓了。
import cn.stylefeng.roses.core.config.WebAutoConfiguration;
import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;
import org.apache.commons.io.IOUtils;
import org.apache.coyote.http11.Http11NioProtocol;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.EnableScheduling;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* SpringBoot方式启动类
*/
@SpringBootApplication(exclude = {WebAutoConfiguration.class})
@EnableScheduling
public class GunnyApplication {
private final static Logger logger = LoggerFactory.getLogger(GunnyApplication.class);
public static void main(String[] args) {
SpringApplication.run(GunnyApplication.class, args);
logger.info(GunnyApplication.class.getSimpleName() + " is success!");
}
@Bean
public Connector createSslConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
ClassPathResource resource = new ClassPathResource("https.keystore");
// 临时目录
String tempPath =System.getProperty("java.io.tmpdir") + System.currentTimeMillis()+".keystore";
File f = new File(tempPath);
logger.info(".keystore目录临时存储路径" + tempPath);
try {
// 将key的值转存到临时文件
IOUtils.copy(resource.getInputStream(),new FileOutputStream(f));
connector.setScheme("https");
connector.setSecure(true);
connector.setPort(8099);
protocol.setSSLEnabled(true);
// 指向临时文件
protocol.setKeystoreFile(f.getAbsolutePath());
protocol.setKeystorePass("123456");
protocol.setKeyAlias("https");
protocol.setKeyPass("123456");
} catch (IOException e) {
e.printStackTrace();
}
return connector;
}
@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory(Connector connector){
TomcatServletWebServerFactory tomcat=new TomcatServletWebServerFactory(){
@Override
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(connector);
return tomcat;
}
}
测试
浏览器试一下就知道效果,已经是https了。