SpringBoot添加SSL证书,开启HTTPS方式(单向认证服务端)

 更新时间:2024年03月05日 09:10:13   作者:喵喵@香菜  
这篇文章主要介绍了SpringBoot添加SSL证书,开启HTTPS方式(单向认证服务端),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

一、前言

通过HTTP协议传输数据,并不会对数据进行加密,所以存在着一定的风险,容易被抓包破解数据,而且现在各种浏览器对使用HTTP协议的网站也会提示不安全。

通过将HTTP协议升级为HTTPS协议可以提高安全系数。使用HTTPS协议就需要了解一下SSL协议。

SSL(Secure Sockets Layer 安全套接字协议),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。

TLS与SSL在传输层与应用层之间对网络连接进行加密。

SSL协议位于TCP/IP协议与各种应用层协议之间,为数据通讯提供安全支持。

SSL协议可分为两层:

  • SSL记录协议(SSL Record Protocol):它建立在可靠的传输协议(如TCP)之上,为高层协议提供数据封装、压缩、加密等基本功能的支持。
  • SSL握手协议(SSL Handshake Protocol):它建立在SSL记录协议之上,用于在实际的数据传输开始前,通讯双方进行身份认证、协商加密算法、交换加密密钥等。

服务器认证阶段:

1)客户端向服务器发送一个开始信息“Hello”以便开始一个新的会话连接;

2)服务器根据客户的信息确定是否需要生成新的主密钥,如需要则服务器在响应客户的“Hello”信息时将包含生成主密钥所需的信息;

3)客户根据收到的服务器响应信息,产生一个主密钥,并用服务器的公开密钥加密后传给服务器;

4)服务器恢复该主密钥,并返回给客户一个用主密钥认证的信息,以此让客户认证服务器。

用户认证阶段:

  • 在此之前,服务器已经通过了客户认证,这一阶段主要完成对客户的认证。
  • 经认证的服务器发送一个提问给客户,客户则返回(数字)签名后的提问和其公开密钥,从而向服务器提供认证。

SSL协议提供的安全通道有以下三个特性:

  • 机密性:SSL协议使用密钥加密通信数据。
  • 可靠性:服务器和客户都会被认证,客户的认证是可选的。
  • 完整性:SSL协议会对传送的数据进行完整性检查。

从SSL 协议所提供的服务及其工作流程可以看出,SSL协议运行的基础是商家对消费者信息保密的承诺,这就有利于商家而不利于消费者。

在电子商务初级阶段,由于运作电子商务的企业大多是信誉较高的大公司,因此这问题还没有充分暴露出来。

但随着电子商务的发展,各中小型公司也参与进来,这样在电子支付过程中的单一认证问题就越来越突出。

虽然在SSL3.0中通过数字签名和数字证书可实现浏览器和Web服务器双方的身份验证,但是SSL协议仍存在一些问题,比如,只能提供交易中客户与服务器间的双方认证,在涉及多方的电子交易中,SSL协议并不能协调各方间的安全传输和信任关系。

在这种情况下,Visa和 MasterCard两大信用卡公司组织制定了SET协议,为网上信用卡支付提供了全球性的标准。

以上摘自百度。

二、SpringBoot中配置SSL(单向)

SSL证书的颁发必须是公开公认的CA机构颁发的,在浏览器中才会被认可是合法的;

SSL证书是针对域名的,单域名的SSL证书对非该域名也是无效的通配域名证书对一级域名和二级域名都有效。

例如:你有一个域名为 abc.com的一级域名,解析了一个.abc.com的二级域名和 b.abc.com的二级域名。当你为a.abc.com申请的单域名证书对b.abc.com域名是无效的。

(PS:我看了网上很多通过keytool生成证书的,通过keytool生成的证书是自签证书,不被浏览器锁认可)

1、环境

spring boot 2.2.2

maven

一个域名(各大域名商有售,阿里、腾讯、华为)

SSL证书(阿里云上有免费的SSL证书,有效期一年)

2、客户端单向认证服务端代码实战-JKS格式的证书

tomcat中支持JKS格式与PFX两种格式的证书,下面先进行JKS格式的证书演示。

(1)准备一个JKS后缀的SSL证书。(域名.jks)

(2)快速构建一个springboot模块

(3) 在resources下新建一个ssl目录,复制SSL证书到该目录下

(4)在项目配置文件application.yml中配置SSL

server:
  port: 8090 #端口配置
  ssl: #ssl配置
    enabled: true  # 默认为true
    #key-alias: alias-key # 别名(可以不进行配置)
    # 保存SSL证书的秘钥库的路径
    key-store: classpath:ssl/service.一级域名.jks
    key-password: 私钥密码
    #key-store-password: 证书密码
    key-store-type: JKS    证书类型

上述配置中 key-password 是私钥密码

key-store-password 是证书密码。

如果这两个密码相同的只配置一个即可,因为tomcat默认先用keyStore的pass去解私钥。(PS:如果你使用阿里云上的免费SSL证书,下载jks格式的证书的时候,只有一个密码,是证书的密码)

(5)添加一个controller,测试是否生效

@RestController
public class TestController {

    @RequestMapping(value = {"","/"})
    public String testHttps(){
        return "you success by https";
    }
}

(6)本地访问 https://127.0.0.1:8090/

因为该证书对应的域名解析的服务器地址与现在访问的地址不同,所以浏览器会提示访问不安全,点击【高级】后的【继续前往…】继续跳转,发现会有很明显的不安全提示。

(7)打包,放到域名解析对应的服务器上进行测试,访问:

https://域名:8090/

可以看到当部署到域名解析对应的服务器上时,通过浏览器访问,浏览器出现一个小锁的标识。

(8)本地使用http访问: http://127.0.0.1:8090/

服务器http访问:http://域名:8090/

通过上述访问发现,如果通过http访问会提示访问需要组合TLS,但是如果用户直接通过这种方式访问的话,存在着极差的用户体验。

3、HTTP 转HTTPS

当用户使用http访问的时候,将http协议重定向到https端口

(1)修改配置文件

custom:  # 自定义http启动端口
  http-port: 8089
配置
server:
  port: 8090 #端口配置  
  ssl: #ssl配置
    enabled: true  # 默认为true
    #key-alias: alias-key # 别名(可以不进行配置)
    # 保存SSL证书的秘钥库的路径
    key-store: classpath:ssl/service.一级域名.jks
    key-password: 私钥密码
    #key-store-password: 证书密码
    key-store-type: JKS

(2)添加配置类

package cn.zlc.servicehttps.config;

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;

/**
 * https配置,将http请求全部转发到https
 * @author Jacob
 */
@Configuration
public class HttpsConfig {

    @Value("${custom.http-port: 8080}")
    private Integer httpPort;

    @Value("${server.port}")
    private Integer port;

    @Bean
    public TomcatServletWebServerFactory servletContainer() {
        // 将http请求转换为https请求
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
            @Override
            protected void postProcessContext(Context context) {
                SecurityConstraint constraint = new SecurityConstraint();
                // 默认为NONE
                constraint.setUserConstraint("CONFIDENTIAL");
                SecurityCollection collection = new SecurityCollection();
                // 所有的东西都https
                collection.addPattern("/*");
                constraint.addCollection(collection);
                context.addConstraint(constraint);
            }
        };
        tomcat.addAdditionalTomcatConnectors(httpConnector());
        return tomcat;
    }

    /**
     * 强制将所有的http请求转发到https
     * @return httpConnector
     */
    @Bean
    public Connector httpConnector() {
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setScheme("http");
        // connector监听的http端口号
        connector.setPort(httpPort);
        connector.setSecure(false);
        // 监听到http的端口号后转向到的https的端口号
        connector.setRedirectPort(port);
        return connector;
    }
}

(3)启动成功后可以看见http启动端口和https端口

(4)本地访问http的8089端口 http://127.0.0.1:8089/

程序会将http端口的请求转发到https端口,而用户无需做操作。

本地直接访问https端口和在服务器上直接访问就不贴图了。

4、同时开启HTTP和HTTPS

如果我们不想强制所有的请求都重定向到https或者某些功能接口需要http的支持等等,我们也可以同时开启http协议和https协议。

(1)修改配置类

package cn.zlc.servicehttps.config;

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;

/**
 * https配置,将http请求全部转发到https
 * @author Jacob
 */
@Configuration
public class HttpsConfig {

    @Value("${custom.http-port: 8080}")
    private Integer httpPort;
    
    @Bean
    public TomcatServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        tomcat.addAdditionalTomcatConnectors(httpConnector());
        return tomcat;
    }

    @Bean
    public Connector httpConnector() {
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setPort(httpPort);
        return connector;
    }

}

(2)本地访问http协议的8089端口:http://127.0.0.1:8089/

(3)本地访问https的8090端口

通过对比发现,如果我们通过http端口请求的话,不会自动重定向到https端口,而且也不会提示需要TLS端口请求。

而使用https请求的时候就会提示不安全(如果是放到服务器上访问https就正常了);

5、客户端单向认证服务端代码实战-PFX格式的证书

(1)配置文件如下:

custom:
  http-port: 8070
server:
  port: 8060 #端口配置
  ssl: #ssl配置
    enabled: true  # 默认为true
    #key-alias: alias-key # 别名(可以不进行配置)
    # 保存SSL证书的秘钥库的路径
    key-store: classpath:ssl/5986342_一级域名.pfx
    #key-password: 私钥密码 pfx格式的使用key-password 无法正常启动
    key-store-type: PKCS12  #证书类型
    key-store-password: 证书密码

(2)不同点

主要的不同点就是key-store-type类型不同,同时如果是JKS的证书,使用私钥密码或者是证书密码都行,但是pfx的证书如果只配置私钥密码无法正常启动。

三、异常解决

使用jks格式的证书时,通过maven打包会出现证书内容被修改,导致证书验证失败,出现Invalid keystore format sl证书格式不合法的异常,可在maven中添加一个插件

 <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.2.0</version>
                <configuration>
                    <nonFilteredFileExtensions>
                        <!--<nonFilteredFileExtension>p12</nonFilteredFileExtension>-->
                        <nonFilteredFileExtension>jks</nonFilteredFileExtension>
                    </nonFilteredFileExtensions>
                </configuration>
            </plugin>

其它解决方案,可查看我的另一篇博客:

异常:Invalid keystore format,spring boot配置ssl证书格式不合法解决

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • IDEA2021.2永久激活码最新超详细(激活到2099)

    IDEA2021.2永久激活码最新超详细(激活到2099)

    这篇文章主要介绍了IDEA2021.2永久激活码,是idea2021版最新激活方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • 在Action中以Struts2的方式输出JSON数据的实例

    在Action中以Struts2的方式输出JSON数据的实例

    下面小编就为大家带来一篇在Action中以Struts2的方式输出JSON数据的实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-11-11
  • Java行为型模式中命令模式分析

    Java行为型模式中命令模式分析

    在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时可以使用命令模式来进行设计
    2023-02-02
  • Spring Boot命令行运行器的实现方法

    Spring Boot命令行运行器的实现方法

    这篇文章主要介绍了Spring Boot命令行运行器的实现方法,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-10-10
  • Spring Cloud Stream如何实现服务之间的通讯

    Spring Cloud Stream如何实现服务之间的通讯

    这篇文章主要介绍了Spring Cloud Stream如何实现服务之间的通讯,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • Java如何处理图片保存之后变红色的问题

    Java如何处理图片保存之后变红色的问题

    这篇文章主要介绍了Java如何处理图片保存之后变红色的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • JavaSE-面向对象(方法重写)

    JavaSE-面向对象(方法重写)

    子类在调用父类的私有方法中不能直接调用,但是可以通过get方法进行调用,修改属性的值可以通过set方法进行修改。而子类想要修改父类中的方法可以使用方法重写进行操作。
    2021-08-08
  • Java集合框架之Stack Queue Deque使用详解刨析

    Java集合框架之Stack Queue Deque使用详解刨析

    早在 Java 2 中之前,Java 就提供了特设类。比如:Dictionary, Vector, Stack, 和 Properties 这些类用来存储和操作对象组。虽然这些类都非常有用,但是它们缺少一个核心的,统一的主题。由于这个原因,使用 Vector 类的方式和使用 Properties 类的方式有着很大不同
    2021-10-10
  • JavaWeb中Struts2拦截器深入分析(一)

    JavaWeb中Struts2拦截器深入分析(一)

    这篇文章主要为大家详细介绍了JavaWeb中Struts2拦截器的功能,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • springboot控制层传递参数为非必填值的操作

    springboot控制层传递参数为非必填值的操作

    这篇文章主要介绍了springboot控制层传递参数为非必填值的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10

最新评论