springboot实现https双向传输协议的示例代码

 更新时间:2025年03月14日 09:41:24   作者:WellAdjested  
本文主要介绍了springboot实现https双向传输协议的示例代码,包含配置证书和私钥路径、调用请求方法等步骤,具有一定的参考价值,感兴趣的可以了解一下

1.https 双向传输协议概念

1.1. 单向认证

  • 我们在通常访问一个网站,例如百度。这是一个单向的TLS认证。
  • 具体的过程为:
    • 服务器发送证书给客户端。
    • 客户端验证证书有效之后,客户端和服务器协商出一个对称加密密钥。
    • 由服务端的私钥加密,并发送给客户端。
    • 客户端收到之后再用公钥解密这个对称密钥。然后就开始用对称密钥加密传输的数据。
  • 特征:
    • 服务端并不校验客户端的合法性,来者不拒,绝大部分的网站都是这种类型。
    • 只有客户端校验服务器端的合法性。

1.2. 双向认证

  • 有时候我们在一些安全性要求较高的场景下,服务器也需要来校验客户端的合法性。
  • 具体的过程为:
    • 在客户端验证了服务器证书的合法性之后,客户端需要带上自己的证书发送给服务器。
    • 服务器收到证书之后,比对服务器在信任链中是否信任了客户端的证书。
    • 如果信任,则服务端校验客户端合法。
    • 如果证书不在服务端的受信列表上,则拒绝服务。
  • 这样子其实就是建立了一条双向认证的TLS传输通道。即互相校验证书。

1.3. 非对称加密交互流程

  • 如果用到的是非对称加密,那么你和第三方之间就有两对公私钥,各自持有对方的公钥和自己的私钥。网络通讯中我们一般用自己的私钥将报文加签,用第三方提供的公钥将报文中涉及安全隐私的部分加密,然后第三方会用我们提供公钥进行验签,验签通过后再用他们自己的私钥将报文加密部分解密;

1.4. csr文件

  • CSR 即证书签名申请(Certificate Signing Request),获取 SSL 证书,需要先生成 CSR 文件并提交给证书颁发机构(CA)。CSR 包含了用于签发证书的公钥、用于辨识的名称信息(Distinguished Name)(例如域名)、真实性和完整性保护(例如数字签名),通常从 Web 服务器生成 CSR;
  • 证书申请者只要把CSR文件提交给证书颁发机构后,证书颁发机构使用其根证书私钥签名就生成了证书公钥文件,也就是颁发给用户的证书。

1.5. 生成证书相关流程

# 1. 生成客户端csr和私钥key 执行这个指令后会生成csr文件和私钥key
openssl req -new -nodes -sha256 -newkey rsa:2048 -keyout privateKey.key -out request.csr

# 生成csr文件后,将csr文件发送给甲方,甲方签发了ca.pem给我们

# 后续访问甲方接口,就一直携带ca.pem和本地私钥 用于传输过程中的文件和数据加密;

2. 使用springboot实现https双向传输协议实例

2.1. 配置证书和私钥路径

  • 在配置文件中配置证书和私钥路径,使得项目能够访问到;
  • ca.pem,privateKey.key

2.2. 调用请求方法

 // 调用方法
    resp = apiService.request(true, POST, url, req);

2.3. ApiService层方法

  @Override
    public String request(Boolean ssl, HttpMethod method, String url, String reqBody) throws Exception {
        // 调用下方的request方法
        return request(ssl, method, url, null, reqBody);
    }

    //    双向认证请求
    @Override
    public String request(Boolean ssl, HttpMethod method, String url, MultiValueMap<String, String> params,
            String reqBody)
            throws Exception {
        logger.info("request url to server =====> {}", url);
        logger.info("request body to server =====> {}", reqBody);
        // 根据实际需求添加请求头
        HttpHeaders headers = new HttpHeaders();
        headers.set("token", "");

        ResponseEntity<String> resp = sslService.request(ssl, url, method, headers, params, reqBody);
        String respBody = resp.getBody();
        logger.info("resp body from server =====> {}", respBody);
        return respBody;
    }

2.4. sslService类中方法

        @Override
        public ResponseEntity<String> request(Boolean ssl, String url, HttpMethod method, HttpHeaders headers,
                        MultiValueMap<String, String> params, String reqBody) throws Exception {

                HttpsClient client = !ssl ? new HttpsClient(ssl)
                                : new HttpsClient(ssl, "证书路径", "私钥路径");
                return RestClientUtil.request(client, url, method, headers, params, reqBody);

        }

2.5. HTTPS通信双向认证工具类

        /**
         * @Description //HTTPS通信双向认证工具类
         **/

        @Data
        public class HttpsClient {
        
            // true-启用双向认证,false-不启用
            private boolean ssl;
            // 服务端公钥
            private String serverPem;
            // 客户端私钥
            private String clientSK;

            public HttpsClient() {
            }

            public HttpsClient(Boolean ssl) {
                this.ssl = ssl;
            }

            public HttpsClient(Boolean ssl, String serverPem, String clientSK) {
                this.ssl = ssl;
                this.serverPem = serverPem;
                this.clientSK = clientSK;
            }

}

2.6. RestClientUtil类中方法

public static ResponseEntity<String> request(HttpsClient client, String url, HttpMethod method,
            HttpHeaders httpHeaders,
            MultiValueMap<String, String> params,
            String reqBody) throws Exception {
        httpHeaders.set("Content-Type", "application/json; charset=utf-8");
        HttpEntity<?> requestEntity = new HttpEntity<>(reqBody, httpHeaders);

        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url).queryParams(params);
//        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url).queryParams(params);
        RestTemplate rest = client.isSsl()
                ? new RestTemplate(HttpsClientUtil.rsaHttpComponentsClientHttpRequestFactory(client))
                : new RestTemplate(generateHttpRequestFactory());
        return rest.exchange(builder.toUriString(), method, requestEntity, String.class);
    }

  /**
     * 忽略SSL证书
     *
     * @return
     */
    private static HttpComponentsClientHttpRequestFactory generateHttpRequestFactory() {

        TrustStrategy acceptingTrustStrategy = (x509Certificates, authType) -> true;

        SSLContext sslContext = null;

        try {

            sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();

        } catch (NoSuchAlgorithmException e) {

            e.printStackTrace();

        } catch (KeyManagementException e) {

            e.printStackTrace();

        } catch (KeyStoreException e) {

            e.printStackTrace();

        }

        SSLConnectionSocketFactory connectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
                new NoopHostnameVerifier());

        HttpClientBuilder httpClientBuilder = HttpClients.custom();

        httpClientBuilder.setSSLSocketFactory(connectionSocketFactory);

        CloseableHttpClient httpClient = httpClientBuilder.build();

        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();

        factory.setHttpClient(httpClient);

        return factory;
    }

2.7. HttpsClientUtil类中方法

 public static HttpComponentsClientHttpRequestFactory rsaHttpComponentsClientHttpRequestFactory(HttpsClient client)
            throws Exception {
        // 获取httpClient对象,防止重复创建--读取证书信息,对象生成后不做其他操作所以未加锁
        if (httpClient == null) {
            httpClient = createCloseableHttpClientByRsa(client);
        }
        HttpComponentsClientHttpRequestFactory httpsFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
//        httpsFactory.setReadTimeout(5000);
//        httpsFactory.setConnectTimeout(5000);
        httpsFactory.setReadTimeout(60 * 1000);
        httpsFactory.setConnectTimeout(60 * 1000);
        return httpsFactory;
    }

到此这篇关于springboot实现https双向传输协议的示例代码的文章就介绍到这了,更多相关springboot https双向传输内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • 客户端设置超时时间真的很重要

    客户端设置超时时间真的很重要

    今天小编就为大家分享一篇关于客户端设置超时时间真的很重要,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • Java中两种抛出异常的方式示例详解

    Java中两种抛出异常的方式示例详解

    在Java中有两种抛出异常的方式,一种是throw,直接抛出异常,另一种是throws,间接抛出异常,本文给大家详细说明java中两种抛出异常的方式,感兴趣的朋友一起看看吧
    2023-08-08
  • Java经典排序算法之归并排序实现代码

    Java经典排序算法之归并排序实现代码

    这篇文章主要介绍了Java经典排序算法之归并排序实现代码,归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用,将已有序的子序列合并,得到完全有序的序列,需要的朋友可以参考下
    2023-10-10
  • Java中报错org.springframework.jdbc.UncategorizedSQLException的多种解决方法

    Java中报错org.springframework.jdbc.UncategorizedSQLException的多种

    本文主要介绍了Java中报错org.springframework.jdbc.UncategorizedSQLException的多种解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06
  • springboot使用IDEA远程Debug

    springboot使用IDEA远程Debug

    项目上线之后,如果日志打印的很模糊或者业务逻辑比较复杂,有时候无法定位具体的错误原因,因此可以通过IDEA远程代理进行Debug,本文就来介绍一下如何使用
    2021-06-06
  • 关于@Scheduled参数及cron表达式解释

    关于@Scheduled参数及cron表达式解释

    这篇文章主要介绍了关于@Scheduled参数及cron表达式解释,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • 使用Java编写控制JDBC连接、执行及关闭的工具类

    使用Java编写控制JDBC连接、执行及关闭的工具类

    这篇文章主要介绍了如何使用Java来编写控制JDBC连接、执行及关闭的程序,包括一个针对各种数据库通用的释放资源的工具类的写法,需要的朋友可以参考下
    2016-03-03
  • Java调用ChatGPT(基于SpringBoot和Vue)实现可连续对话和流式输出的ChatGPT API

    Java调用ChatGPT(基于SpringBoot和Vue)实现可连续对话和流式输出的ChatGPT API

    这篇文章主要介绍了Java调用ChatGPT(基于SpringBoot和Vue),实现可连续对话和流式输出的ChatGPT API(可自定义实现AI助手),文中代码示例介绍的非常详细,感兴趣的朋友可以参考下
    2023-04-04
  • Java Set接口及常用实现类总结

    Java Set接口及常用实现类总结

    Collection的另一个子接口就是Set,他并没有我们List常用,并且自身也没有一些额外的方法,全是继承自Collection中的,因此我们还是简单总结一下,包括他的常用实现类HashSet、LinkedHashSet、TreeSet的总结
    2023-01-01
  • Java编程实现NBA赛事接口调用实例代码

    Java编程实现NBA赛事接口调用实例代码

    这篇文章主要介绍了Java编程实现NBA赛事接口调用实例代码,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11

最新评论