http与https

HTTP
HTTP(HyperText Transfer Protocol,超文本传输协议),是因特网应用最广的协议。

原生的HTTP通信存在如下风险:

  1. 窃听风险:第三方可以获取通信内容。
  2. 篡改风险:第三方可以修改通信内容。
  3. 冒充风险:第三方可以冒充他人身份参与通信。

HTTPS = HTTP+ SSL /TLS
HTTPS是使用HTTP协议和SSL连接构建的可进行加密传输、身份认证的网络协议。
SSL/TLS协议就是为了解决HTTP三大风险而设计的,希望达到:

  1. 所有信息都是加密传输,第三方无法窃听。
  2. 具有校验机制,一旦被篡改,通信双方会立刻发现。
  3. 配备身份证书,防止身份被冒充。

SSL/TLS握手过程

  1. 客户端发出请求(ClientHello),向服务器提供以下信息:
    1. 支持的协议版本
    2. 客户端生成的随机数(用于生成对话密钥)
    3. 支持的加密方法
    4. 支持的压缩方法
  2. 服务器发出回应(ServerHello),向客户端回应以下内容:
    1. 确认使用的加密通信协议版本
    2. 服务器生成的随机数(用于生成对话密钥)
    3. 确认使用的加密方法
    4. 服务器证书
  3. 客户端收到服务器回应,首先验证证书,没有问题则从证书中取出服务器公钥,然后向服务器发送以下内容:
    1. 一个随机数(用于服务器公钥加密)
    2. 编码改变通知,表示随后的消息都将用双方商定的加密方法和密钥发送
    3. 客户端握手结束通知,表示客户端的握手阶段已经结束(这一项是前面发送的所有内容的hash值,用于供服务器校验)
  4. 服务器收到第三个随机数之后,使用协商的加密算法计算出本地会话密钥,然后向客户端发送以下信息:
    1. 编码改变通知,表示随后的信息都将采用双方商定的加密方法和密钥发送。
    2. 服务器握手结束通知,表示服务器的握手阶段已经结束。(这一项也是前面发送的所有内容的hash值,用于供客户端校验)

注意:生成会话密钥使用的是非对称加密,会话过程使用的是对称加密。 前者保证计算出的密钥的安全性,后者侧重通信过程中加解密的性能。

CA证书

参考:https://www.iteye.com/blog/wlh269-733398

CA是证书的签发机构,是PKI的核心。
作为负责签发证书、认证证书和管理证书的机关,它要制定政策和具体步骤来验证、识别用户身份,并对用户证书进行签名,以确保证书持有者的身份和公钥的拥有权。
存在的意义:假设不存在认证机构,任何人都可以制作证书,这带来的安全风险便是经典的中间人攻击问题。

CA架构

springboot-https - 图1

包含信息

  1. 颁发机构信息
  2. 公钥
  3. 公司信息
  4. 域名
  5. 有效期
  6. 指纹

浏览器验证证书的合法性

  1. 验证域名和有效期是否正确;
  2. 判断证书来源是否合法;
  3. 判断证书是否被篡改;
  4. 判断证书是否已吊销。


项目准备

使用maven构建项目,使用Tomcat作为服务器:

  1. <properties>
  2. <maven.compiler.source>1.8</maven.compiler.source>
  3. <maven.compiler.target>1.8</maven.compiler.target>
  4. <spring.boot.version>2.2.2.RELEASE</spring.boot.version>
  5. </properties>
  6. <dependencies>
  7. <dependency>
  8. <groupId>org.springframework.boot</groupId>
  9. <artifactId>spring-boot-starter-web</artifactId>
  10. <version>${spring.boot.version}</version>
  11. </dependency>
  12. </dependencies>
  13. <build>
  14. <plugins>
  15. <plugin>
  16. <groupId>org.springframework.boot</groupId>
  17. <artifactId>spring-boot-maven-plugin</artifactId>
  18. </plugin>
  19. </plugins>
  20. </build>

生成证书

借助jdk工具:

  1. keytool -genkey
  2. -alias <name>(别名)
  3. -keypass <key_password>(别名密码)
  4. -keyalg <algorithm>(生证书的算法名称,RSA是一种非对称加密算法)
  5. -keysize <size>(密钥长度,证书大小)
  6. -validity <days>(证书有效期,天单位)
  7. -keystore <file_path>(指定生成证书的位置和证书名称)
  8. -storepass <store_password>(获取keystore信息的密码)
  9. - storetype (指定密钥仓库类型)

例如:

  1. > keytool -genkey -alias tomcat -keypass KAG1823 -keyalg RSA -keysize 1024 -validity 365 -keystore K:/tomcat.keystore -storepass KAG1823 -storetype PKCS12
  2. 您的名字与姓氏是什么?
  3. [Unknown]: Khighness
  4. 您的组织单位名称是什么?
  5. [Unknown]: parak.top
  6. 您的组织名称是什么?
  7. [Unknown]: parak
  8. 您所在的城市或区域名称是什么?
  9. [Unknown]: Wuhan
  10. 您所在的省/市/自治区名称是什么?
  11. [Unknown]: Hubei
  12. 该单位的双字母国家/地区代码是什么?
  13. [Unknown]: zh
  14. CN=Khighness, OU=parak.top, O=parak, L=Wuhan, ST=Hubei, C=zh是否正确?
  15. [否]: y

将生成的文件放在resources下面。

项目配置

application.properties

  1. # Server
  2. server.port=11111
  3. server.http-port=22222
  4. spring.application.name=springboot-https
  5. # KeyStore
  6. server.ssl.enabled=true
  7. server.ssl.key-store=classpath:tomcat.keystore
  8. server.ssl.key-store-type=PKCS12
  9. server.ssl.key-alias=tomcat
  10. server.ssl.key-store-password=KAG1823

项目编码

HttpsConfiguration

  1. import org.apache.catalina.Context;
  2. import org.apache.catalina.connector.Connector;
  3. import org.apache.tomcat.util.descriptor.web.SecurityCollection;
  4. import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
  5. import org.springframework.beans.factory.annotation.Value;
  6. import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.context.annotation.Configuration;
  9. /**
  10. * @author KHighness
  11. * @since 2021-04-05
  12. * @apiNote http强制跳转https
  13. */
  14. @Configuration
  15. public class HttpsConfiguration {
  16. @Value("${server.port}")
  17. private Integer sslPort;
  18. @Value("${server.http-port}")
  19. private Integer httpPort;
  20. @Bean
  21. public TomcatServletWebServerFactory servletWebServerFactory() {
  22. TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
  23. @Override
  24. protected void postProcessContext(Context context) {
  25. // 设置安全性约束
  26. SecurityConstraint securityConstraint = new SecurityConstraint();
  27. securityConstraint.setUserConstraint("CONFIDENTIAL");
  28. // 设置约束条件
  29. SecurityCollection collection = new SecurityCollection();
  30. // 拦截所有请求
  31. collection.addPattern("/*");
  32. securityConstraint.addCollection(collection);
  33. context.addConstraint(securityConstraint);
  34. }
  35. };
  36. Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
  37. // 设置将分配给通过此连接器接收到的请求的方案
  38. connector.setScheme("http");
  39. // true: http使用http, https使用https
  40. // false:http重定向到https
  41. connector.setSecure(false);
  42. // 设置监听请求的端口号
  43. connector.setPort(httpPort);
  44. // 重定向端口号(非SSL到SSL)
  45. connector.setRedirectPort(sslPort);
  46. tomcat.addAdditionalTomcatConnectors(connector);
  47. return tomcat;
  48. }
  49. }

CommonController

  1. import org.springframework.web.bind.annotation.GetMapping;
  2. import org.springframework.web.bind.annotation.PathVariable;
  3. import org.springframework.web.bind.annotation.RestController;
  4. /**
  5. * @author KHighness
  6. * @since 2021-04-05
  7. */
  8. @RestController
  9. public class CommonController {
  10. @GetMapping("/hello/{name}")
  11. public String index(@PathVariable("name") String name) {
  12. return "Hello, " + name;
  13. }
  14. }

KHighnessApplication

  1. import org.springframework.boot.SpringApplication;
  2. import org.springframework.boot.autoconfigure.SpringBootApplication;
  3. /**
  4. * @author KHighness
  5. * @since 2021-04-05
  6. */
  7. @SpringBootApplication
  8. public class KHighnessApplication {
  9. public static void main(String[] args) {
  10. SpringApplication.run(KHighnessApplication.class, args);
  11. }
  12. }

运行测试

打开浏览器,输入:http://localhost:22222/hello/Khighness
一般会提示非安全连接,忽略即可。
直接前往,重定向:https://localhost:11111/hello/Khighness
image.png