前言
HTTP 具有相当优秀和方便的一面,然而 HTTP 并非只有好的一面,事物皆具两面性,它也是有不足之处的。例如:
- 通信使用明文(不加密),内容可能会被窃听。
- 不验证通信方的身份,因此有可能会遭遇伪装。
- 无法证明报文的完整性,所以有可能会遭篡改等。
因HTTP有存在通信上的不足,HTTPS因此诞生(HTTPS 是身披 SSL 外壳的 HTTP),HTTPS采用非对称加密,从而相对安全。
SSL协议介绍
SSL (Secure Sockets Layer)安全套接层,是一个不依赖于平台和运用程序的协议,位于TCP/IP协议与各种应用层协议之间,为数据通信提高安全支持。
是由Netscape公司于1990年开发,用于保障Word Wide Web(WWW)通讯的安全。主要任务是提供私密性,信息完整性和身份认证。
SSL原理详解
SSL的体系结构中包含两个协议子层,其中底层是SSL记录协议层(SSL Record Protocol Layer);高层是SSL握手协议层(SSL HandShake Protocol Layer)。
- SSL记录协议层的作用是为高层协议提供基本的安全服务。SSL纪录协议针对HTTP协议进行了特别的设计,使得超文本的传输协议HTTP能够在SSL运行。纪录封装各种高层协议,具体实施压缩解压缩、加密解密、计算和校验MAC等与安全有关的操作。
- SSL握手协议层包括SSL握手协议(SSL HandShake Protocol)、SSL密码参数修改协议(SSL Change
Cipher Spec Protocol)和SSL告警协议(SSL Alert
Protocol)。握手层的这些协议用于SSL管理信息的交换,允许应用协议传送数据之间相互验证,协商加密算法和生成密钥等。
SSL握手协议的作用是协调客户和服务器的状态,使双方能够达到状态的同步。
其中最重要的是记录协议和握手协议:
- SSL记录协议:它建立在可靠的传输(如TCP)之上,为高层协议提供数据封装、压缩、加密等基本功能
- SSL握手协议:它建立在SSL记录协议之上,用于在实际的数据传输开始之前,通讯双方进行身份认证、协商加密算法、交换加密密钥等。
整合HTTPS
SSL证书的颁发必须是公开公认的CA机构颁发的,在浏览器中才会被认可是合法的;
SSL证书是针对域名的,单域名的SSL证书对非该域名是无效的,通配域名证书对一级域名和二级域名都有效。
生成自签名SSL
在JDK bin目录下,运行:
# D:\java\key 此地址为存放目录,需要自己创建
keytool -genkey -alias tomcat -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore D:\java\key\keystore.p12 -validity 3650 -ext san=ip:127.0.0.1,dns:localhost -storepass 123456
输入密钥库口令:
再次输入新口令:
您的名字与姓氏是什么?
[Unknown]:
您的组织单位名称是什么?
[Unknown]:
您的组织名称是什么?
[Unknown]:
您所在的城市或区域名称是什么?
[Unknown]:
您所在的省/市/自治区名称是什么?
[Unknown]:
该单位的双字母国家/地区代码是什么?
[Unknown]:
CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown是否正确?
[否]: 是
各参数的含义:
- -storetype 指定密钥仓库类型
- -keyalg 生证书的算法名称,RSA是一种非对称加密算法
- -keysize 证书大小,秘钥长度
- -keystore 生成的证书文件的存储路径
- -validity 证书的有效期,单位 天
- -alias 表示keystore的别名
- -genkey 表示要创建一个新秘钥
- -ext san=ip: 安装证书后,通过这个IP进行访问不会提示不安全,多个IP使用[,]分隔
- -ext san=dns: 安装证书后,通过这个域名进行访问不会提示不安全,多个域名使用[,]分隔
执行完上面一行命令后,在你的系统的当前用户目录下会生成一个keystore.p12文件,我们也可以使用以下命令查看证书内容:
keytool -list -v -storetype pkcs12 -keystore keystore.p12
如果你已经有SSL证书,你也可将其导入到keystore里,供Spring Boot使用
keytool -import -alias tomcat -file myCertificate.crt -keystore keystore.p12 -storepass password
配置文件
将这个文件拷贝到我们项目的resources目录下,然后修改application.properties文件,添加HTTPS支持。
server:
port: 443
servlet:
context-path: /
session:
timeout: PT24H # 超时24小时
ssl:
#文件地址
key-store: classpath:certificate/keystore.p12
#证书密码
key-store-password: 123456
key-store-type: PKCS12
key-alias: tomcat
http2:
enabled: true
这样就可以通过HTTPS来访问我们的Web了。
配置HTTP重定向至HTTPS
光有HTTPS肯定还不够,很多用户可能并不知道,用户有可能继续使用HTTP来访问你的网站,这个时候我们需要添加HTTP自动重定向到HTTPS的功能,当用户使用HTTP来进行访问的时候自动转为HTTPS的方式。
配置很简单,在入口类中添加相应的重定向Bean就行了,如下:
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.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @ClassName: ConnectorConfig
* @description:
* @author: Liuxb
* @version: v1.0
* @date: 2023/10/26 14:47
*/
@Configuration
public class ConnectorConfig {
@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;
}
@Bean
public Connector connector (){
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
connector.setSecure(false);
// 代理端口
connector.setPort(80);
// yml端口
connector.setRedirectPort(443);
return connector;
}
}
这个时候当我们访问http://localhost:80的时候系统会自动重定向到https://localhost:443这个地址上。