首先,你需要获取有效的 SSL 证书和私钥。SSL 证书是一种用于加密通信的数字证书,它可以通过购买商业 SSL 证书或使用免费的 Let’s Encrypt 证书获得。请确保你拥有证书文件和与之对应的私钥文件,这通常是以 .pem 和 .key 结尾的文件或者是jks格式的,本文以jks格式的SSL证书为例。
接下来,我们将配置 Spring Boot 项目以使用 SSL。
spring boot 2.2.2
maven
一个域名(各大域名商有售,阿里、腾讯、华为)
SSL证书(阿里云上有免费的SSL证书,有效期一年)
将之前获取的 SSL 证书和私钥文件拷贝到 Spring Boot 项目中的 src/main/resources 目录下。这样,证书文件会与项目一起打包并在运行时加载。
在 Spring Boot 项目的配置文件(application.properties 或 application.yml)中添加以下 SSL 相关配置:
server: port: 8856 servlet: context-path: / ssl: enabled: true # 保存SSL证书的秘钥库的路径 key-store: classpath:ssl/xxx.com.jks key-store-password: xxx # 证书类型 key-store-type: JKS # key-store-protocol: TLS
添加一个controller,测试是否生效,测试结果如下:
通过上述访问发现,如果通过http访问会提示访问需要组合TLS,但是如果用户直接通过这种方式访问的话,存在着极差的用户体验。
当用户使用http访问的时候,将http协议重定向到https端口
(1)修改配置文件
custom: # 自定义http启动端口 http-port: 8857 server: port: 8856 servlet: context-path: / ssl: enabled: true #key-alias: alias-key # 别名(可以不进行配置) # 保存SSL证书的秘钥库的路径 key-store: classpath:ssl/xxx.com.jks key-store-password: xxx # 证书类型 key-store-type: JKS # key-store-protocol: TLS
(2)添加配置类
package org.pp.ssl.config; import org.apache.catalina.Context; import org.apache.catalina.connector.Connector; import org.apache.tomcat.util.descriptor.web.SecurityCollection; import org.apache.tomcat.util.descriptor.web.SecurityConstraint; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * https配置,将http请求全部转发到https * @author P_P */ @Configuration public class HttpsConfig { @Value("${custom.http-port: 8857}") private Integer httpPort; @Value("${server.port}") private Integer port; @Bean public TomcatServletWebServerFactory servletContainer() { // 将http请求转换为https请求 TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() { @Override protected void postProcessContext(Context context) { SecurityConstraint constraint = new SecurityConstraint(); // 默认为NONE constraint.setUserConstraint("CONFIDENTIAL"); SecurityCollection collection = new SecurityCollection(); // 所有的东西都https collection.addPattern("/*"); constraint.addCollection(collection); context.addConstraint(constraint); } }; tomcat.addAdditionalTomcatConnectors(httpConnector()); return tomcat; } /** * 强制将所有的http请求转发到https * * @return httpConnector */ @Bean public Connector httpConnector() { Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); connector.setScheme("http"); // connector监听的http端口号 connector.setPort(httpPort); connector.setSecure(false); // 监听到http的端口号后转向到的https的端口号 connector.setRedirectPort(port); return connector; } }
(3)启动项目
添加配置类之后,启动项目可以看到控制台出现了https端口和http端口
再次访问测试接口,会发现地址栏出现了https
(4)同时开启http和https
如果不想将http请求都转发到https进行处理,可以同时开启http和https
/** * 同时开启http和https * @author P_P */ import org.apache.catalina.connector.Connector; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class HttpsConfig { @Value("${custom.http-port: 8857}") private Integer httpPort; @Bean public TomcatServletWebServerFactory servletContainer() { TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); tomcat.addAdditionalTomcatConnectors(httpConnector()); return tomcat; } @Bean public Connector httpConnector() { Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); connector.setPort(httpPort); return connector; } }
这样访问8857(http协议)的端口就不会进行转发了
springBoot中配置了一个bean,bean加载的时候,会进行jks的加载,jks文件放在src/resources下,然后就报错了,错误如下。
2023-08-03 22:22:27.261:[ERROR] [main:6839] [org.springframework.boot.SpringApplication.reportFailure:826] --> Application run failed org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat server at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:215) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.startWebServer(ServletWebServerApplicationContext.java:297) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:163) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:553) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) at org.ee.authority.AuthorityApplication.main(AuthorityApplication.java:28) Caused by: java.lang.IllegalArgumentException: Invalid keystore format at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:99) ~[tomcat-embed-core-9.0.29.jar:9.0.29] at org.apache.tomcat.util.net.AbstractJsseEndpoint.initialiseSsl(AbstractJsseEndpoint.java:71) ~[tomcat-embed-core-9.0.29.jar:9.0.29] at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:218) ~[tomcat-embed-core-9.0.29.jar:9.0.29] at org.apache.tomcat.util.net.AbstractEndpoint.bindWithCleanup(AbstractEndpoint.java:1142) ~[tomcat-embed-core-9.0.29.jar:9.0.29] at org.apache.tomcat.util.net.AbstractEndpoint.start(AbstractEndpoint.java:1228) ~[tomcat-embed-core-9.0.29.jar:9.0.29] at org.apache.coyote.AbstractProtocol.start(AbstractProtocol.java:586) ~[tomcat-embed-core-9.0.29.jar:9.0.29] at org.apache.catalina.connector.Connector.startInternal(Connector.java:1005) ~[tomcat-embed-core-9.0.29.jar:9.0.29] Caused by: java.lang.IllegalArgumentException: standardService.connector.startFailed at org.apache.catalina.core.StandardService.addConnector(StandardService.java:231) at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.addPreviouslyRemovedConnectors(TomcatWebServer.java:278) at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.start(TomcatWebServer.java:197) ... 10 common frames omitted Caused by: org.apache.catalina.LifecycleException: Protocol handler start failed at org.apache.catalina.connector.Connector.startInternal(Connector.java:1008) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.core.StandardService.addConnector(StandardService.java:227) ... 12 common frames omitted 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:1142) at org.apache.tomcat.util.net.AbstractEndpoint.start(AbstractEndpoint.java:1228) at org.apache.coyote.AbstractProtocol.start(AbstractProtocol.java:586) at org.apache.catalina.connector.Connector.startInternal(Connector.java:1005) ... 14 common frames omitted Caused by: java.io.IOException: Invalid keystore format at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:666) at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:57) at sun.security.provider.KeyStoreDelegator.engineLoad(KeyStoreDelegator.java:224) at sun.security.provider.JavaKeyStore$DualFormatJKS.engineLoad(JavaKeyStore.java:71) at java.security.KeyStore.load(KeyStore.java:1449) 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:283) at org.apache.tomcat.util.net.SSLUtilBase.createSSLContext(SSLUtilBase.java:247) at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:97) ... 20 common frames omitted
直接用main函数解析jks文件,一点毛病都没有。但是打包后启动Tomact再解析就不行,直接启动单元测试(完整加载bean的形式)也不行。
后来发现,在target文件夹下,jks文件的大小变了。查了资料,大概明白错误的根本原因了:maven编译或者打包的时候,对文件的内容进行了修改(maven编译的时候使用了占位符,替换的时候使文件发生了变化),这就导致了jks文件发生变化。
配置MAVEN过滤JKS等格式的文件,在pom的build配置中增加如下过滤配置,将jks过滤掉。(提一句,以下配置中也过滤了xlsx,是因为打包后Excel文件也会坏掉)
org.springframework.boot spring-boot-maven-plugin org.apache.maven.plugins maven-resources-plugin ${project.build.sourceEncoding} true true pem pfx p12 key xlsx jks org.apache.maven.plugins maven-javadoc-plugin 3.0.0
上一篇:后端八股笔记-----mysql