http与https
HTTP
HTTP(HyperText Transfer Protocol,超文本传输协议),是因特网应用最广的协议。
原生的HTTP通信存在如下风险:
- 窃听风险:第三方可以获取通信内容。
- 篡改风险:第三方可以修改通信内容。
- 冒充风险:第三方可以冒充他人身份参与通信。
HTTPS = HTTP+ SSL /TLS
HTTPS是使用HTTP协议和SSL连接构建的可进行加密传输、身份认证的网络协议。
SSL/TLS协议就是为了解决HTTP三大风险而设计的,希望达到:
- 所有信息都是加密传输,第三方无法窃听。
- 具有校验机制,一旦被篡改,通信双方会立刻发现。
- 配备身份证书,防止身份被冒充。
SSL/TLS握手过程
- 客户端发出请求(ClientHello),向服务器提供以下信息:
- 支持的协议版本
- 客户端生成的随机数(用于生成对话密钥)
- 支持的加密方法
- 支持的压缩方法
- 服务器发出回应(ServerHello),向客户端回应以下内容:
- 确认使用的加密通信协议版本
- 服务器生成的随机数(用于生成对话密钥)
- 确认使用的加密方法
- 服务器证书
- 客户端收到服务器回应,首先验证证书,没有问题则从证书中取出服务器公钥,然后向服务器发送以下内容:
- 一个随机数(用于服务器公钥加密)
- 编码改变通知,表示随后的消息都将用双方商定的加密方法和密钥发送
- 客户端握手结束通知,表示客户端的握手阶段已经结束(这一项是前面发送的所有内容的hash值,用于供服务器校验)
- 服务器收到第三个随机数之后,使用协商的加密算法计算出本地会话密钥,然后向客户端发送以下信息:
- 编码改变通知,表示随后的信息都将采用双方商定的加密方法和密钥发送。
- 服务器握手结束通知,表示服务器的握手阶段已经结束。(这一项也是前面发送的所有内容的hash值,用于供客户端校验)
注意:生成会话密钥使用的是非对称加密,会话过程使用的是对称加密。 前者保证计算出的密钥的安全性,后者侧重通信过程中加解密的性能。
CA证书
CA是证书的签发机构,是PKI的核心。
作为负责签发证书、认证证书和管理证书的机关,它要制定政策和具体步骤来验证、识别用户身份,并对用户证书进行签名,以确保证书持有者的身份和公钥的拥有权。
存在的意义:假设不存在认证机构,任何人都可以制作证书,这带来的安全风险便是经典的中间人攻击问题。
CA架构

包含信息
- 颁发机构信息
- 公钥
- 公司信息
- 域名
- 有效期
- 指纹
浏览器验证证书的合法性
- 验证域名和有效期是否正确;
- 判断证书来源是否合法;
- 判断证书是否被篡改;
- 判断证书是否已吊销。
项目准备
使用maven构建项目,使用Tomcat作为服务器:
<properties><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><spring.boot.version>2.2.2.RELEASE</spring.boot.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>${spring.boot.version}</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
生成证书
借助jdk工具:
keytool -genkey-alias <name>(别名)-keypass <key_password>(别名密码)-keyalg <algorithm>(生证书的算法名称,RSA是一种非对称加密算法)-keysize <size>(密钥长度,证书大小)-validity <days>(证书有效期,天单位)-keystore <file_path>(指定生成证书的位置和证书名称)-storepass <store_password>(获取keystore信息的密码)- storetype (指定密钥仓库类型)
例如:
> keytool -genkey -alias tomcat -keypass KAG1823 -keyalg RSA -keysize 1024 -validity 365 -keystore K:/tomcat.keystore -storepass KAG1823 -storetype PKCS12您的名字与姓氏是什么?[Unknown]: Khighness您的组织单位名称是什么?[Unknown]: parak.top您的组织名称是什么?[Unknown]: parak您所在的城市或区域名称是什么?[Unknown]: Wuhan您所在的省/市/自治区名称是什么?[Unknown]: Hubei该单位的双字母国家/地区代码是什么?[Unknown]: zhCN=Khighness, OU=parak.top, O=parak, L=Wuhan, ST=Hubei, C=zh是否正确?[否]: y
将生成的文件放在resources下面。
项目配置
application.properties
# Serverserver.port=11111server.http-port=22222spring.application.name=springboot-https# KeyStoreserver.ssl.enabled=trueserver.ssl.key-store=classpath:tomcat.keystoreserver.ssl.key-store-type=PKCS12server.ssl.key-alias=tomcatserver.ssl.key-store-password=KAG1823
项目编码
HttpsConfiguration
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;/*** @author KHighness* @since 2021-04-05* @apiNote http强制跳转https*/@Configurationpublic class HttpsConfiguration {@Value("${server.port}")private Integer sslPort;@Value("${server.http-port}")private Integer httpPort;@Beanpublic TomcatServletWebServerFactory servletWebServerFactory() {TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {@Overrideprotected void postProcessContext(Context context) {// 设置安全性约束SecurityConstraint securityConstraint = new SecurityConstraint();securityConstraint.setUserConstraint("CONFIDENTIAL");// 设置约束条件SecurityCollection collection = new SecurityCollection();// 拦截所有请求collection.addPattern("/*");securityConstraint.addCollection(collection);context.addConstraint(securityConstraint);}};Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");// 设置将分配给通过此连接器接收到的请求的方案connector.setScheme("http");// true: http使用http, https使用https// false:http重定向到httpsconnector.setSecure(false);// 设置监听请求的端口号connector.setPort(httpPort);// 重定向端口号(非SSL到SSL)connector.setRedirectPort(sslPort);tomcat.addAdditionalTomcatConnectors(connector);return tomcat;}}
CommonController
import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RestController;/*** @author KHighness* @since 2021-04-05*/@RestControllerpublic class CommonController {@GetMapping("/hello/{name}")public String index(@PathVariable("name") String name) {return "Hello, " + name;}}
KHighnessApplication
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;/*** @author KHighness* @since 2021-04-05*/@SpringBootApplicationpublic class KHighnessApplication {public static void main(String[] args) {SpringApplication.run(KHighnessApplication.class, args);}}
运行测试
打开浏览器,输入:http://localhost:22222/hello/Khighness
一般会提示非安全连接,忽略即可。
直接前往,重定向:https://localhost:11111/hello/Khighness
