简单的 HTTPS 学习

简单的 HTTPS 学习

1. 需求

现在使用的服务是HTTP调用形式,服务可能会有调用外围https形式的服务,简单了解了一下,然后写了一个简单的例子进行记录。

HTTP(超文本传输协议) 是一种用于传输超文本的应用层协议,建立在TCP/IP协议栈之上。它定义了客户端(如浏览器)如何向服务器请求资源,以及服务器如何响应这些请求。

HTTPS(超文本传输安全协议) 是HTTP协议的安全版本,它在HTTP与TCP之间加入了SSL/TLS加密层,通过加密数据传输来保障数据的安全性和完整性。

他们的主要区别如下所示:

  • 安全性

    HTTP协议不加密传输的数据,任何人都可以轻易地获取和篡改传输的内容,存在严重的安全风险。

    为了解决HTTP协议的安全问题,HTTPS应运而生。

    HTTPS协议通过SSL/TLS加密传输的数据,即使数据被拦截,攻击者也无法解密,有效地保障了数据的安全。

  • 数据传输方式

    HTTP使用的是不安全的TCP端口80进行数据传输,而HTTPS使用的是更安全的TCP端口443,并通过 SSL/TLS 协议对数据进行加密后再传输,进一步提升了数据传输的安全性。

  • 部署成本

    HTTP协议是免费的,不需要额外的证书。

    而HTTPS协议需要SSL/TLS证书,这些证书通常需要从受信任的证书颁发机构(CA)购买。

  • 性能

    由于需要进行加密和解密操作,HTTPS协议可能会略微影响网站的加载速度。

    但是,随着现代硬件和优化加密算法的应用,这种影响已经被大大降低。

2. 准备

测试环境,我们使用JDK自带的工具生成测试证书,我们此次的调用形式使用RestTemplate进行调用,调用形式分为以下情况

  • http 服务调用 https 服务 (服务端验证)
  • https 服务调用 https 服务(客户端 服务端双向验证)

2.1 准备证书秘钥信息

我们本地使用 keytool 工具生成,我本地工具类位置如下C:\Program Files\Java\jdk1.8.0_131\bin

然后需要使用PowerShell 工具进入到keytool目录中,执行命令生成两份证书信息,对应两个https服务使用,我们要输入秘钥口令,以及其他基础信息

shell 复制代码
# 参数含义如下:
# keytool: 表示keytool工具
# genkey: 表示要创建一个新的密钥。
# alias: 表示 keystore 的别名。anyname 都可以。
# storetype: 表示密钥的仓库类型,存储格式是PKCS12.
# keyalg: 表示使用的加密算法是 RSA ,一种非对称加密算法。
# keysize: 表示密钥的长度。这里是2048.
# keystore: 表示生成的证书文件存放位置。 这里是D:\httpsSecurityKey.p12
# validity: 表示证书的有效时间365天。
keytool -genkey -alias httpsSecurity -storetype PKCS12 -keyalg RSA -keysize 2048  -keystore D:\https_security_key\httpsSecurityKey.p12 -validity 365

keytool -genkey -alias httpsSecuritySecond -storetype PKCS12 -keyalg RSA -keysize 2048  -keystore D:\https_security_key\httpsSecuritySecondKey.p12 -validity 365

然后执行命令生成两份公钥文件

shell 复制代码
# 从密钥库中提取公钥证书到独立的证书文件
# 从 httpsSecurityKey.p12 中导出证书部分
# 生成 httpsSecurity.cer 证书文件(只包含公钥和身份信息,不含私钥)
# 这个证书文件可以安全地分发给其他方
keytool -export -alias httpsSecurity -keystore D:\https_security_key\httpsSecurityKey.p12 -storetype PKCS12 -file D:\https_security_key\httpsSecurity.cer

# 将证书添加到信任库中,表示信任该证书持有者
# 创建或更新 truststore.jks 信任库文件
# 将 httpsSecurity.cer 证书导入信任库
# 设置该证书为"受信任的",用于验证对方身份
keytool -import -alias httpsSecurity -file D:\https_security_key\httpsSecurity.cer -keystore D:\https_security_key\truststore.jks

# 从密钥库中提取公钥证书到独立的证书文件...
keytool -export -alias httpsSecuritySecond -keystore D:\https_security_key\httpsSecuritySecondKey.p12 -storetype PKCS12 -file D:\https_security_key\httpsSecuritySecond.cer

# 将证书添加到信任库中,表示信任该证书持有者...
keytool -import -alias httpsSecuritySecond -file D:\https_security_key\httpsSecuritySecond.cer -keystore D:\https_security_key\truststoreSecond.jks

最终执行完毕后,会在目录中看到这些文件

2.2 编写代码

此次测试我们用到了三个服务,分别为http-server,https-server以及 https-server-second,整体的项目结构如下:

2.2.1 引入pom

服务引入pom分为根pom,服务pom,具体内容如下所示

  1. 服务根pom

    xml 复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>cn.git</groupId>
        <artifactId>https-test</artifactId>
        <version>1.0-SNAPSHOT</version>
        <modules>
            <module>http-server</module>
            <module>https-server</module>
            <module>https-server-second</module>
        </modules>
        <packaging>pom</packaging>
    
        <properties>
            <!-- 如果项目部署要给其他人使用,则此值必须填写为true,否则父级pom不上传,会引起子jar包无法下载情况 -->
            <maven.deploy.skip>false</maven.deploy.skip>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
    
            <mybatis-plus.version>3.3.0</mybatis-plus.version>
            <fastjson.version>1.2.83</fastjson.version>
            <druid.version>1.2.4</druid.version>
            <oracle.version>11.2.0.4.0-atlassian-hosted</oracle.version>
    
            <hutool.version>5.5.7</hutool.version>
            <lombok.version>1.18.6</lombok.version>
            <mapstruct.version>1.4.1.Final</mapstruct.version>
            <swagger.version>3.0.0</swagger.version>
    
            <elasticjob.version>3.0.0-RC1</elasticjob.version>
    
            <poi-tl.version>1.9.1</poi-tl.version>
            <poi.version>4.1.2</poi.version>
            <easyexcel.version>2.2.8</easyexcel.version>
            <tomcat.version>9.0.44</tomcat.version>
        </properties>
    
        <!-- springboot dependency -->
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.3.8.RELEASE</version>
            <relativePath/>
        </parent>
    
        <!-- 部署到私库 -->
        <distributionManagement>
            <repository>
                <id>git</id>
                <name>git-releases</name>
                <url>http://3.1.101.57:8081/repository/maven-releases/</url>
            </repository>
            <snapshotRepository>
                <id>git</id>
                <name>git-snapshot</name>
                <url>http://3.1.101.57:8081/repository/maven-snapshots/</url>
            </snapshotRepository>
        </distributionManagement>
    
        <dependencyManagement>
            <dependencies>
                <!-- fastjson -->
                <dependency>
                    <groupId>com.alibaba</groupId>
                    <artifactId>fastjson</artifactId>
                    <version>${fastjson.version}</version>
                </dependency>
                <!-- hutool -->
                <dependency>
                    <groupId>cn.hutool</groupId>
                    <artifactId>hutool-all</artifactId>
                    <version>${hutool.version}</version>
                </dependency>
                <!-- lombok -->
                <dependency>
                    <groupId>org.projectlombok</groupId>
                    <artifactId>lombok</artifactId>
                    <version>${lombok.version}</version>
                </dependency>
                <!-- mapstruct -->
                <dependency>
                    <groupId>org.mapstruct</groupId>
                    <artifactId>mapstruct</artifactId>
                    <version>${mapstruct.version}</version>
                </dependency>
                <!-- swagger -->
                <dependency>
                    <groupId>io.springfox</groupId>
                    <artifactId>springfox-boot-starter</artifactId>
                    <version>${swagger.version}</version>
                </dependency>
                <!-- poi -->
                <dependency>
                    <groupId>com.deepoove</groupId>
                    <artifactId>poi-tl</artifactId>
                    <version>${poi-tl.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.apache.poi</groupId>
                    <artifactId>poi</artifactId>
                    <version>${poi.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.apache.poi</groupId>
                    <artifactId>poi-ooxml</artifactId>
                    <version>${poi.version}</version>
                </dependency>
                <!-- easyexcel -->
                <dependency>
                    <groupId>com.alibaba</groupId>
                    <artifactId>easyexcel</artifactId>
                    <version>${easyexcel.version}</version>
                </dependency>
            </dependencies>
        </dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </dependency>
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>${fastjson.version}</version>
            </dependency>
        </dependencies>
    
    </project>
  2. 服务pom

    xml 复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>https-test</artifactId>
            <groupId>cn.git</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>https-server-second</artifactId>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-logging</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.6</version>
            </dependency>
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>5.5.7</version>
            </dependency>
            <dependency>
                <groupId>org.mapstruct</groupId>
                <artifactId>mapstruct</artifactId>
                <version>1.4.1.Final</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.83</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-logging</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-log4j2</artifactId>
            </dependency>
            <dependency>
                <groupId>com.lmax</groupId>
                <artifactId>disruptor</artifactId>
                <version>3.3.4</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-autoconfigure</artifactId>
            </dependency>
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
                <version>4.5.14</version>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <!-- compiler -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                        <annotationProcessorPaths>
                            <path>
                                <groupId>org.mapstruct</groupId>
                                <artifactId>mapstruct-processor</artifactId>
                                <version>1.4.1.Final</version>
                            </path>
                            <path>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                                <version>${lombok.version}</version>
                            </path>
                        </annotationProcessorPaths>
                    </configuration>
                </plugin>
                <!-- package -->
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
                <!-- maven私服jar包部署插件 -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>${maven-deploy-plugin.version}</version>
                    <configuration>
                        <skip>false</skip>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>

2.2.2 http-server服务

RestTemplate配置部分代码

java 复制代码
package cn.git.http.config;

import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.cert.CertificateException;

/**
 * @description: RestTemplate 配置类
 * @program: bank-credit-sy
 * @author: lixuchun
 * @create: 2025-08-13
 */
@Configuration
public class RestTemplateConfig {

    @Value("${client.ssl.trust-store}")
    private String trustStorePath;

    @Value("${client.ssl.trust-store-password}")
    private String trustStorePassword;

    @Value("${client.ssl.trust-store-type}")
    private String trustStoreType;

    /**
     * 创建RestTemplate实例
     *
     * @return
     * @throws KeyStoreException
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     */
    @Bean
    public RestTemplate restTemplate() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
        // 加载https服务提供的公钥信息
        KeyStore trustStore = KeyStore.getInstance(trustStoreType);

        try {
            // 处理 classpath 资源
            ClassPathResource resource = new ClassPathResource(trustStorePath);
            InputStream in = resource.getInputStream();
            trustStore.load(in, trustStorePassword.toCharArray());
            in.close();
        } catch (IOException | NoSuchAlgorithmException | CertificateException e) {
            e.printStackTrace();
        }

        // 构建SSL上下文
        SSLContext sslContext = SSLContextBuilder.create()
                // 信任的证书
                .loadTrustMaterial(trustStore, null)
                .build();

        SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext,
                // 禁用主机名验证
                NoopHostnameVerifier.INSTANCE);
        HttpClient httpClient = HttpClients.custom()
                .setSSLSocketFactory(socketFactory)
                .build();

        HttpComponentsClientHttpRequestFactory factory =
                new HttpComponentsClientHttpRequestFactory(httpClient);
        return new RestTemplate(factory);
    }
}

请求controller代码

java 复制代码
package cn.git.http.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @description: httpController测试接口
 * @program: bank-credit-sy
 * @author: lixuchun
 * @create: 2025-08-13
 */
@Slf4j
@RestController
@RequestMapping("/http")
public class HttpController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/getHttpInfo")
    public String getHttpInfo() {
        log.info("getHttpInfo");
        return "http";
    }

    /**
     * GET获取https服务信息
     *
     * @return
     */
    @GetMapping("/getHttpsInfo")
    public String getHttpsInfo() {
        return restTemplate.getForObject("https://3.2.36.116:443/https/getHttpsInfo", String.class);
    }

    /**
     * POST获取https服务信息
     *
     * @return
     */
    @GetMapping("/getPostHttpsInfo")
    public String getPostHttpsInfo() {
        String requestBody = "{\"id\":\"1\",\"name\": \"jack\"}";

        // 创建请求头,设置Content-Type为JSON
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        // 创建HttpEntity
        HttpEntity<String> requestEntity = new HttpEntity<>(requestBody, headers);

        // POST请求,调用https服务
        return restTemplate.postForObject("https://3.2.36.116:443/https/getPostHttpsInfo", requestEntity, String.class);
    }
}

application.yaml配置文件内容

yaml 复制代码
spring:
  application:
    name: @project.artifactId@
  main:
    allow-bean-definition-overriding: true

server:
  port: 80

# https-server 客户端公钥密码配置
client:
  ssl:
    # 服务端提供信任库文件
    trust-store: truststore.jks
    trust-store-type: JKS
    # 信任库文件密码
    trust-store-password: 888666li

并且我们需要将生成的信任库文件放入到 resoures 目录之中

2.2.3 https-server服务

controller测试接口文件

java 复制代码
package cn.git.https.controller;

import cn.git.https.vo.HttpsInVO;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.*;

/**
 * @description: httpController测试接口
 * @program: bank-credit-sy
 * @author: lixuchun
 * @create: 2025-08-13
 */
@RestController
@RequestMapping("/https")
public class HttpsController {

    @GetMapping("/getHttpsInfo")
    public String getHttpInfo() {
        return "https";
    }

    @PostMapping("/getPostHttpsInfo")
    public String getPostHttpInfo(@RequestBody HttpsInVO httpsInVO) {
        return JSONObject.toJSONString(httpsInVO);
    }
}

POST形式调用参数inVO文件

java 复制代码
package cn.git.https.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @description: 传入inVO
 * @program: bank-credit-sy
 * @author: lixuchun
 * @create: 2025-08-13
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class HttpsInVO {
    private String id;
    private String name;
}

application.yaml 服务配置文件

yaml 复制代码
spring:
  application:
    name: @project.artifactId@
  main:
    allow-bean-definition-overriding: true

server:
  port: 443
  ssl:
    # 服务器端HTTPS证书
    key-store: classpath:httpsSecurityKey.p12
    # 服务器端HTTPS证书密码
    key-store-password: 666888li
    # 服务器端HTTPS证书别名
    key-alias: httpsSecurity
    # 服务器端HTTPS证书类型,默认JKS
    key-store-type: PKCS12

    # 新增的双向认证配置
    # 信任库(包含客户端公钥证书)
    trust-store: classpath:truststoreSecond.jks
    # 信任库密码
    trust-store-password: 888666secondli
    # 要求客户端认证 : want-不强制希望,need-强制,none-不认证
    client-auth: need

注意,我们需要将生成的服务证书以及另一个https服务提供的信任库文件放到resources目录中

2.2.4 https-server-second服务

RestTemplate配置,此为双向验证,所以与http-server的restTemplate配置略有不同

java 复制代码
package cn.git.https.config;

import cn.hutool.core.util.StrUtil;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.cert.CertificateException;

/**
 * @description: RestTemplate 配置类
 * @program: bank-credit-sy
 * @author: lixuchun
 * @create: 2025-08-13
 */
@Configuration
public class RestTemplateConfig {

    @Value("${client.ssl.trust-store}")
    private String trustStorePath;

    @Value("${client.ssl.trust-store-password}")
    private String trustStorePassword;

    @Value("${client.ssl.trust-store-type}")
    private String trustStoreType;

    @Value("${server.ssl.key-store}")
    private String keyStorePath;

    @Value("${server.ssl.key-store-password}")
    private String keyStorePassword;

    @Value("${server.ssl.key-store-type}")
    private String keyStoreType;

    /**
     * 创建RestTemplate实例
     *
     * @return
     * @throws KeyStoreException
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     */
    @Bean
    public RestTemplate restTemplate() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException, UnrecoverableKeyException {
        // 加载客户端证书(用于双向认证)
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        try {
            // 处理 classpath 资源
            ClassPathResource resource = new ClassPathResource(keyStorePath.substring(10));
            InputStream in = resource.getInputStream();
            keyStore.load(in, keyStorePassword.toCharArray());
            in.close();
        } catch (IOException | NoSuchAlgorithmException | CertificateException e) {
            e.printStackTrace();
        }

        // 加载信任证书
        KeyStore trustStore = KeyStore.getInstance(trustStoreType);
        try {
            // 处理 classpath 资源
            ClassPathResource resource = new ClassPathResource(trustStorePath);
            InputStream in = resource.getInputStream();
            trustStore.load(in, trustStorePassword.toCharArray());
            in.close();
        } catch (IOException | NoSuchAlgorithmException | CertificateException e) {
            e.printStackTrace();
        }

        // 构建SSL上下文
        SSLContext sslContext = SSLContextBuilder.create()
                .loadKeyMaterial(keyStore, keyStorePassword.toCharArray())
                // 信任的证书
                .loadTrustMaterial(trustStore, null)
                .build();

        SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext,
                // 禁用主机名验证
                NoopHostnameVerifier.INSTANCE);

        // 创建HttpClient实例
        HttpClient httpClient = HttpClients.custom()
                .setSSLSocketFactory(socketFactory)
                .build();

        // 创建RestTemplate实例
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
        return new RestTemplate(factory);
    }
}

controller测试接口代码

java 复制代码
package cn.git.https.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @description: second-https controller测试接口
 * @program: bank-credit-sy
 * @author: lixuchun
 * @create: 2025-08-13
 */
@RestController
@RequestMapping("/https")
public class HttpsSecondController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/getLocalHttpsSecondInfo")
    public String getHttpInfo() {
        return "getHttpsSecondInfo";
    }

    /**
     * GET获取https服务信息
     *
     * @return
     */
    @GetMapping("/getHttpsSecondInfo")
    public String getHttpsSecondInfo() {
        return restTemplate.getForObject("https://3.2.36.116:443/https/getHttpsInfo", String.class);
    }

    /**
     * POST获取https服务信息
     *
     * @return
     */
    @GetMapping("/getPostHttpsSecondInfo")
    public String getPostHttpsInfo() {
        String requestBody = "{\"id\":\"1\",\"name\": \"jack\"}";

        // 创建请求头,设置Content-Type为JSON
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        // 创建HttpEntity
        HttpEntity<String> requestEntity = new HttpEntity<>(requestBody, headers);

        // POST请求,调用https服务
        return restTemplate.postForObject("https://3.2.36.116:443/https/getPostHttpsInfo", requestEntity, String.class);
    }
}

application.yaml配置文件信息

yaml 复制代码
spring:
  application:
    name: @project.artifactId@
  main:
    allow-bean-definition-overriding: true

# 服务器端HTTPS配置
server:
  port: 8443
  ssl:
    # 服务器端HTTPS证书
    key-store: classpath:httpsSecuritySecondKey.p12
    # 服务器端HTTPS证书密码
    key-store-password: 666888secondli
    # 服务器端HTTPS证书别名
    key-alias: httpsSecuritySecond
    # 服务器端HTTPS证书类型
    key-store-type: PKCS12

    # 新增的双向认证配置
    # 信任库(包含客户端公钥证书)
    trust-store: classpath:truststore.jks
    # 信任库密码
    trust-store-password: 888666li
    # 要求客户端认证 : want-不强制希望,need-强制,none-不认证
    client-auth: none

# https-server 客户端公钥密码配置
client:
  ssl:
    # 服务端提供信任库文件
    trust-store: truststore.jks
    # 服务端提供信任库文件类型
    trust-store-type: JKS
    # 信任库文件密码
    trust-store-password: 888666li

注意,我们需要将生成的服务证书以及另一个https服务提供的信任库文件放到resources目录中,主要实现双向认证

3. 测试

测试主要分为两种测试,第一个http调用https,第二种https调用https(双向验证)

3.1 http调用 https

http调用https形式的时候,我们需要将https-server服务端的 client-auth 客户端验证禁用,否则访问接口提示如下信息,需要配置浏览器证书信息

禁用客户端验证,将 client-auth 设置为 none

先访问https-server自己服务接口,https://localhost/https/getHttpsInfo,请求结果如下

然后通过http-server接口,restTemplate调用 https-server接口,http://localhost/http/getHttpsInfo 请求结果如下

通过PostMan,访问 https://localhost:443/https/getPostHttpsInfo 进行post请求,请求结果如下

如果禁用 restTemplate配置的SSL证书信任库,然后再发起请求,http://localhost/http/getHttpsInfo 请求结果如下


3.2 https调用https

我们首先开启https-server的客户端验证,现在访问需要进行客户端验证了

我们访问 https-server-second 接口,里面进行了restTemplate调用 https-server接口 https://localhost:8443/https/getHttpsSecondInfo 展示结果如下

如果我注释https-server-second 配置restTemplate的 加载客户端证书(用于双向认证)配置,再次访问https://localhost:8443/https/getHttpsSecondInfo 展示结果如下


项目的源码位置:https://gitee.com/xiaodali/https-test

相关推荐
丁满与彭彭2 小时前
嵌入式学习笔记--MCU阶段--DAY12实时操作系统rt_thread1
笔记·学习
诗书画唱4 小时前
我的学习认知、高效方法与知识积累笔记
笔记·学习
No Silver Bullet4 小时前
HTTPS 工作原理
网络协议·http·https
qq_282195314 小时前
cpp-httplib 测试https功能
网络协议·http·https
Akshsjsjenjd4 小时前
Linux 服务部署:自签 CA 证书构建 HTTPS 及动态 Web 集成
linux·前端·https
我们从未走散5 小时前
设计模式学习笔记-----单例模式
java·笔记·学习·单例模式·设计模式
Xの哲學8 小时前
TCP 连接管理:深入分析四次握手与三次挥手
网络·网络协议·算法
宇寒风暖9 小时前
@(AJAX)
前端·javascript·笔记·学习·ajax
菜菜子爱学习14 小时前
Nginx学习笔记(八)—— Nginx缓存集成
笔记·学习·nginx·缓存·运维开发