前提,我是在自己笔记本上做的。

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的那个。

springboot改造成springcloud springboot改成https_apache

2.项目配置

2.1keystore文件放在resource的根路径下

springboot改造成springcloud springboot改成https_java_02

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了。

springboot改造成springcloud springboot改成https_java_03