前言
基本上现在网络访问都会使用 HTTPS,因此很有必要为我们的后端应用增添 HTTPS 访问能力。
本篇博文主要介绍下在 Spring Boot 下开启 HTTPS 访问配置过程。
准备工作
HTTPS 访问前提是需要有一个 HTTPS 证书,证书的获取过程常见的有如下途径:
- 商用证书:一些专业的商用证书需要我们进行购买,价格也挺贵的。
- 免费证书:网络上有些机构会提供一些免费证书,比如一些云服务器厂商,一个账号可以申请多个证书(20 个左右),证书有效期大概一年左右。
-
本地证书:如果只是对本地 HTTPS 访问进行测试,我们可以直接使用 Java JDK 自带的管理工具
keytool
来生成一个本地证书。
这里我们为 Spring Boot 配置 HTTPS,就直接使用 本地证书 即可,进入到%JAVA_HOME%/bin
目录,执行如下命令生成一个本地数字证书:
keytool -genkey -alias tomcathttps -keyalg RSA -keysize 2048 -keystore whyn.p12 -validity 5
其中:
-
-genkey
:表示创建一个新的密钥 -
-alias
:表示密钥(即 keystore,相当于加密后的私钥)的别名 -
-keyalg RSA
:表示使用的加密算法是 RSA,一种非对称性加密算法 -
-keysize
:表示密钥长度 -
-keystore
:表示生成的密钥存放位置 -
-validity
:表示密钥有效时间,单位为天
执行以上命令,最终会生成一个密钥,我们这里的密钥为:whyn.p12
导入密钥
上面步骤我们已经生成了一个密钥文件whyn.p12
,接下来就可以将其导入到 Spring Boot 项目中了,步骤如下:
-
将密钥
whyn.p12
拷贝到项目resources
目录下 -
在
application.properties
中,配置服务器开启 HTTPS:# 配置端口 server.port=8080 # 配置协议 server.ssl.protocol=TLS # 密钥文件名 server.ssl.key-store=classpath:whyn.p12 # 密钥别名 server.ssl.key-alias=tomcathttps # 密钥密码 server.ssl.key-store-password=123456
以上就已完成了配置,此时运行项目,浏览器输入https://localhost:8080
就可以进行访问。
注:由于我们使用的是自签名证书,不被系统信任,因此第一次访问时,浏览器会出现以下警告页面,此时我们允许继续访问即可。
同时支持 HTTP 和 HTTPS
按上文配置,此时如果我们访问http://localhost:8080
,会发现访问失败,这是因为 Spring Boot 默认不支持同时在配置中启动 HTTP 和 HTTPS。
如果我们想同时支持 HTTP 和 HTTPS,只需将其中一个用代码进行配置即可。
Spring Boot 推荐的做法是使用配置文件配置开启 HTTPS,而使用代码配置开启 HTTP,因为 HTTP 通过代码进行开启的方式相对简单,如下所示:
@Configuration
public class EnableHTTPConfig {
@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
tomcat.addAdditionalTomcatConnectors(createTomcatConnector());
return tomcat;
}
private Connector createTomcatConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setPort(8081);
return connector;
}
}
我们只需向 Spring IOC 容器中注入一个配置Bean
即可,此时运行程序,可以看到以下输出:
可以看到,我们已经成功同时开启了 HTTP 和 HTTPS 协议。
注:实际上,虽然我们能同时启用 HTTP 和 HTTPS,但在实际项目部署时,一般都避免使用 HTTP 进行访问,因为 HTTP 是明文传输,信息很容易被别人截获,使用 HTTPS 的安全性会更高一些。
因此,更加常用的做法是将 HTTP 的访问重定向到对应的 HTTPS 中,具体代码如下:
@Configuration
public class EnableHTTPConfig {
@Bean
TomcatServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
@Override
protected void postProcessContext(Context context) {
SecurityConstraint constraint = new SecurityConstraint();
constraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
constraint.addCollection(collection);
context.addConstraint(constraint);
}
};
tomcat.addAdditionalTomcatConnectors(createTomcatConnector());
return tomcat;
}
private Connector createTomcatConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
connector.setPort(8081);
connector.setSecure(false);
// 重定向到 8080 端口
connector.setRedirectPort(8080);
return connector;
}
}
上述代码中,我们配置了 HTTP 请求的端口为 8081,并配置了将来自 8081 端口的所有请求都重定向到 8080 端口。
网友评论