HTTPS介绍
HTTPS 是http的安全访问协议。
HTTPS 协议是由 HTTP 加上 TLS/SSL 协议构建的可进行加密传输、身份认证的网络协议,主要通过数字证书、加密算法、非对称密钥等技术完成互联网数据传输加密,实现互联网传输安全保护。设计目标主要有三个。
(1)数据保密性:保证数据内容在传输的过程中不会被第三方查看。就像快递员传递包裹一样,都进行了封装,别人无法获知里面装了什么 [4] 。
(2)数据完整性:及时发现被第三方篡改的传输内容。就像快递员虽然不知道包裹里装了什么东西,但他有可能中途掉包,数据完整性就是指如果被掉包,我们能轻松发现并拒收 [4] 。
(3)身份校验安全性:保证数据到达用户期望的目的地。就像我们邮寄包裹时,虽然是一个封装好的未掉包的包裹,但必须确定这个包裹不会送错地方,通过身份校验来确保送对了地方 [4] 。
SSL证书目前市面上有以下几种
- .DER .CER,文件是二进制格式,只保存证书,不保存私钥。
- .PEM,一般是文本格式,可保存证书,可保存私钥。
- .CRT,可以是二进制格式,可以是文本格式,与 .DER 格式相同,不保存私钥。
- .PFX .P12,二进制格式,同时包含证书和私钥,一般有密码保护。
- .JKS,二进制格式,同时包含证书和私钥,一般有密码保护。
JKS是利用JDK来生产的一组秘钥
SpringBoot配置SSL协议
SpringBoot可以通过在application.properties或application.yml配置文件中配置各种server.ssl.*属性来声明性使用SSL(https),
比如下面的例子使用了JKS证书
1
2
3
4
5
6
7
8
9
10
11
12
server:
ssl:
# 证书路径
key-store: classpath:server.keystore
key-alias: tomcat
enabled: true
//证书的类型
key-store-type: JKS
#与申请时输入一致
key-store-password: 123456
# 浏览器默认端口 和 80 类似
port: 443
比如下面的例子使用了pkcs12协议
1
2
3
4
5
6
7
8
9
10
11
12
server:
ssl:
# 证书路径
key-store: classpath:server.keystore
key-alias: tomcat
enabled: true
//证书的类型
key-store-type: pkcs12
#与申请时输入一致
key-store-password: 123456
# 浏览器默认端口 和 80 类似
port: 443
SpringBoot无法同时使得Http和Https协议共存,如果要同时支持,可以通过如下介绍的编程来进行同时支持,具体在下面会讲。
使用JDK工具生成证书
在jdk的bin目录下,通过keytool进行生生成
证书相关
Keytools生成证书
JAVA 的专属格式,一般用于 Tomcat 服务器。
在jdk/bin目录下执行如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
C:\Program Files\Java\jdk1.8.0_251\bin>keytool
密钥和证书管理工具
命令:
-certreq 生成证书请求
-changealias 更改条目的别名
-delete 删除条目
-exportcert 导出证书
-genkeypair 生成密钥对
-genseckey 生成密钥
-gencert 根据证书请求生成证书
-importcert 导入证书或证书链
-importpass 导入口令
-importkeystore 从其他密钥库导入一个或所有条目
-keypasswd 更改条目的密钥口令
-list 列出密钥库中的条目
-printcert 打印证书内容
-printcertreq 打印证书请求的内容
-printcrl 打印 CRL 文件的内容
-storepasswd 更改密钥库的存储口令
使用 "keytool -command_name -help" 获取 command_name 的用法
主要使用genkeypair来生产证书
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
C:\Program Files\Java\jdk1.8.0_251\bin>keytool -genkeypair -help
keytool -genkeypair [OPTION]...
生成密钥对
选项:
-alias <alias> 要处理的条目的别名
-keyalg <keyalg> 密钥算法名称
-keysize <keysize> 密钥位大小
-sigalg <sigalg> 签名算法名称
-destalias <destalias> 目标别名
-dname <dname> 唯一判别名
-startdate <startdate> 证书有效期开始日期/时间
-ext <value> X.509 扩展
-validity <valDays> 有效天数
-keypass <arg> 密钥口令
-keystore <keystore> 密钥库名称
-storepass <arg> 密钥库口令
-storetype <storetype> 密钥库类型
-providername <providername> 提供方名称
-providerclass <providerclass> 提供方类名
-providerarg <arg> 提供方参数
-providerpath <pathlist> 提供方类路径
-v 详细输出
-protected 通过受保护的机制的口令
使用 "keytool -help" 获取所有可用命令
因此生成证书可以使用
1
keytool -genkeypair -alias "tomcat" -keyalg "RSA" -keystore "server.keystore"
参数说明:
1
2
3
4
5
-genkeypair:生成一对非对称密钥;
-alias:指定密钥对的别名,该别名是公开的;
-keyalg:指定加密算法,本例中的采用通用的RAS加密算法;
-keystore:密钥库的路径及名称,不指定的话,默认在操作系统的用户目录下生成一个".keystore"的文件
备注1:关于JDK支持的加密算法,请查看https://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html
备注2:如果你的JDK在C盘,CMD需要使用管理员权限。
注意:
1.密钥库的密码至少必须6个字符,可以是纯数字或者字母或者数字和字母的组合等等
2.”名字与姓氏”一般指的是域名,而不是我们的个人姓名,其他的可以不填
3.最后输入y或者yes均可
执行完上述命令后,在bin目录下生成了一个”server.keystore”的文件
使用SpringBoot进行配置即可访问Https。
生成完成后,会有这样的一行提示信息
1
2
Warning:
JKS 密钥库使用专用格式。建议使用 "keytool -importkeystore -srckeystore server.keystore -destkeystore server.keystore -deststoretype pkcs12" 迁移到行业标准格式 PKCS12。
这说明PKCS12才是行业标准格式,我们需要迁移到行业标准格式
1
keytool -importkeystore -srckeystore server.keystore -destkeystore server.keystore -deststoretype pkcs12
生成后会对旧的keystore文件进行备份,生成old文件,分别进行查看如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
keytool -list -keystore XXX.keystore
C:\Program Files\Java\jdk1.8.0_251\bin>keytool -list -keystore server.keystore
输入密钥库口令:
密钥库类型: PKCS12
密钥库提供方: SUN
您的密钥库包含 1 个条目
tomcat, 2021-12-13, PrivateKeyEntry,
证书指纹 (SHA1): AF:26:10:AA:60:30:DE:58:E9:D0:05:93:74:69:C4:7D:F8:C7:84:3C
C:\Program Files\Java\jdk1.8.0_251\bin>keytool -list -keystore server.keystore.old
输入密钥库口令:
密钥库类型: jks
密钥库提供方: SUN
您的密钥库包含 1 个条目
tomcat, 2021-12-13, PrivateKeyEntry,
证书指纹 (SHA1): AF:26:10:AA:60:30:DE:58:E9:D0:05:93:74:69:C4:7D:F8:C7:84:3C
Warning:
JKS 密钥库使用专用格式。建议使用 "keytool -importkeystore -srckeystore server.keystore.old -destkeystore server.keystore.old -deststoretype pkcs12" 迁移到行业标准格式 PKCS12。
导出证书
比如将server.keystore导出到server.crt中
1
keytool -export -alias tomcat -file server.crt -keystore server.keystore
这样就生成了文件server.crt
导出证书
比如将server.crt导出到test_cacerts证书库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
keytool -import -keystore test_cacerts -file server.crt
C:\Program Files\Java\jdk1.8.0_251\bin>keytool -import -keystore test_cacerts -file server.crt
输入密钥库口令:
再次输入新口令:
所有者: CN=www.test.com, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
发布者: CN=www.test.com, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
序列号: 1186e728
有效期为 Mon Dec 13 22:50:37 CST 2021 至 Sun Mar 13 22:50:37 CST 2022
证书指纹:
MD5: 37:A1:6E:BA:C2:A2:0C:A6:D8:B0:42:8A:E6:55:14:32
SHA1: AF:26:10:AA:60:30:DE:58:E9:D0:05:93:74:69:C4:7D:F8:C7:84:3C
SHA256: 14:71:D4:C4:17:EB:10:A3:61:1E:2E:9D:3A:12:8A:DA:F1:81:E3:90:AE:A8:83:82:6E:E9:E9:B8:03:DB:E6:5B
签名算法名称: SHA256withRSA
主体公共密钥算法: 2048 位 RSA 密钥
版本: 3
扩展:
#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 17 1D BE 58 5A 7E E6 2D 39 4F 4B 16 5F 87 03 AC ...XZ..-9OK._...
0010: 81 15 3E 94 ..>.
]
]
是否信任此证书? [否]: y
证书已添加到密钥库中
查看证书信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
keytool -printcert -file "server.crt"
keytool -printcert -file "****"
C:\Program Files\Java\jdk1.8.0_251\bin>keytool -printcert -file "server.crt"
所有者: CN=www.test.com, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
发布者: CN=www.test.com, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
序列号: 1186e728
有效期为 Mon Dec 13 22:50:37 CST 2021 至 Sun Mar 13 22:50:37 CST 2022
证书指纹:
MD5: 37:A1:6E:BA:C2:A2:0C:A6:D8:B0:42:8A:E6:55:14:32
SHA1: AF:26:10:AA:60:30:DE:58:E9:D0:05:93:74:69:C4:7D:F8:C7:84:3C
SHA256: 14:71:D4:C4:17:EB:10:A3:61:1E:2E:9D:3A:12:8A:DA:F1:81:E3:90:AE:A8:83:82:6E:E9:E9:B8:03:DB:E6:5B
签名算法名称: SHA256withRSA
主体公共密钥算法: 2048 位 RSA 密钥
版本: 3
扩展:
#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 17 1D BE 58 5A 7E E6 2D 39 4F 4B 16 5F 87 03 AC ...XZ..-9OK._...
0010: 81 15 3E 94 ..>.
]
]
删除密钥库中的条目
删除server.keystore中别名为tomcat的证书条目
1
2
3
4
5
6
7
8
9
10
11
12
keytool -delete -keystore server.keystore -alias tomcat
C:\Program Files\Java\jdk1.8.0_251\bin>keytool -delete -keystore server.keystore -alias tomcat
输入密钥库口令:
C:\Program Files\Java\jdk1.8.0_251\bin>keytool -list -keystore server.keystore
输入密钥库口令:
密钥库类型: PKCS12
密钥库提供方: SUN
您的密钥库包含 0 个条目
C:\Program Files\Java\jdk1.8.0_251\bin>
修改证书条目的口令
修改server.keystore的口令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//刚刚被删除了,先导入server
keytool -importpass -alias server -keystore server.keystore
//修改成口令密码
keytool -keypasswd -alias server -keystore server.keystore
C:\Program Files\Java\jdk1.8.0_251\bin>keytool -importpass -alias server -keystore server.keystore
输入密钥库口令:
输入要存储的口令:
再次输入口令:
输入 <server> 的密钥口令
(如果和密钥库口令相同, 按回车):
C:\Program Files\Java\jdk1.8.0_251\bin>keytool -keypasswd -alias server -keystore server.keystore
输入密钥库口令:
新<server> 的密钥口令:
重新输入新<server> 的密钥口令:
C:\Program Files\Java\jdk1.8.0_251\bin>
SpringBoot跳转HTTPS
以下代码实现了从80端口跳转到了HTTPS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@Configuration
public class HttpsConfig {
/**
* 配置 http(80) -> 强制跳转到 https(443)
*/
@Bean
public Connector connector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
connector.setPort(80);
connector.setSecure(false);
connector.setRedirectPort(443);
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;
}
}
SpringBoot同时支持Http和Https
有俩种版本,1是让应用自动支持http,然后手动配置对Https的支持,2是配置自动支持https,如上面,然后让自动支持http
第二种实现简单如下
对于SpringBoot2来说
1
2
3
4
5
6
7
8
9
10
11
12
13
@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
tomcat.addAdditionalTomcatConnectors(createStandardConnector());
return tomcat;
}
// 配置http
private Connector createStandardConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setPort(port);
return connector;
}
SpringBoot1.5.X以下
1
2
3
4
5
6
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
tomcat.addAdditionalTomcatConnectors(createStandardConnector()); // 添加http
return tomcat;
}