利用Java实现mTLS调用

 更新时间:2021年11月04日 10:41:42   作者:banq  
这篇文章主要介绍使用 Java作为客户端 与受 mTLS 保护的服务交互。为了对我们的 Java 客户端进行 ssl 配置,我们需要先设置一个 SSLContext。这简化了事情,因为 SSLContext 可用于各种 http 客户端,接下来我们一起进入下面文章了解具体内容,需要的朋友可以参考一下

本文将使用 Java作为客户端 与受 mTLS 保护的服务交互。

为了对我们的 Java 客户端进行 ssl 配置,我们需要先设置一个 SSLContext。这简化了事情,因为 SSLContext 可用于各种 http 客户端。

由于我们有客户端公钥和私钥,我们需要将私钥从 PEM 格式转换为 DER。

openssl pkcs8 -topk8 -inform PEM -outform PEM -in /path/to/generated/client.key -out /path/to/generated/client.key.pkcs8 -nocrypt

下一步是将客户端密钥加载到 Java 代码中并创建一个 KeyManagerFactory:

String privateKeyPath = <font>"/path/to/generated/client.key.pkcs8"</font><font>;
String publicKeyPath = </font><font>"/path/to/generated/client.crt"</font><font>;
 
<b>final</b> byte[] publicData = Files.readAllBytes(Path.of(publicKeyPath));
<b>final</b> byte[] privateData = Files.readAllBytes(Path.of(privateKeyPath));
 
String privateString = <b>new</b> String(privateData, Charset.defaultCharset())
        .replace(</font><font>"-----BEGIN PRIVATE KEY-----"</font><font>, </font><font>""</font><font>)
        .replaceAll(System.lineSeparator(), </font><font>""</font><font>)
        .replace(</font><font>"-----END PRIVATE KEY-----"</font><font>, </font><font>""</font><font>);
 
byte[] encoded = Base64.getDecoder().decode(privateString);
 
<b>final</b> CertificateFactory certificateFactory = CertificateFactory.getInstance(</font><font>"X.509"</font><font>);
<b>final</b> Collection<? <b>extends</b> Certificate> chain = certificateFactory.generateCertificates(
        <b>new</b> ByteArrayInputStream(publicData));
 
Key key = KeyFactory.getInstance(</font><font>"RSA"</font><font>).generatePrivate(<b>new</b> PKCS8EncodedKeySpec(encoded));
 
KeyStore clientKeyStore = KeyStore.getInstance(</font><font>"jks"</font><font>);
<b>final</b> <b>char</b>[] pwdChars = </font><font>"test"</font><font>.toCharArray();
clientKeyStore.load(<b>null</b>, <b>null</b>);
clientKeyStore.setKeyEntry(</font><font>"test"</font><font>, key, pwdChars, chain.toArray(<b>new</b> Certificate[0]));
 
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(</font><font>"SunX509"</font><font>);
keyManagerFactory.init(clientKeyStore, pwdChars);

在上面的片段中

  • 我们从文件中读取字节。
  • 我们从公钥创建了一个证书链。
  • 我们使用私钥创建了一个密钥实例。
  • 使用链和密钥创建了一个密钥库
  • 创建了一个 KeyManagerFactory

现在我们已经创建了一个 KeyManagerFactory 我们可以使用它来创建一个 SSLContext

由于使用自签名证书,我们需要使用接受它们的 TrustManager。在此示例中,信任管理器将接受服务器提供的所有证书。

TrustManager[] acceptAllTrustManager = {
                <b>new</b> X509TrustManager() {
                    <b>public</b> X509Certificate[] getAcceptedIssuers() {
                        <b>return</b> <b>new</b> X509Certificate[0];
                    }
 
                    <b>public</b> <b>void</b> checkClientTrusted(
                            X509Certificate[] certs, String authType) {
                    }
 
                    <b>public</b> <b>void</b> checkServerTrusted(
                            X509Certificate[] certs, String authType) {
                    }
                }
        };

然后ssl上下文初始化。

SSLContext sslContext = SSLContext.getInstance(<font>"TLS"</font><font>);
sslContext.init(keyManagerFactory.getKeyManagers(), acceptAllTrustManager, <b>new</b> java.security.SecureRandom());


客户端代码:

HttpClient client = HttpClient.newBuilder()
                                     .sslContext(sslContext)
                                     .build();
 
 
 
       HttpRequest exactRequest = HttpRequest.newBuilder()
                                     .uri(URI.create(<font>"https://127.0.0.1"</font><font>))
                                     .GET()
                                     .build();
 
       <b>var</b> exactResponse = client.sendAsync(exactRequest, HttpResponse.BodyHandlers.ofString())
                                 .join();
       System.out.println(exactResponse.statusCode());


我们将收到一个 404 代码,这意味着我们的请求成功进行了 mTLS 握手。

注意:如果服务器端是使用本地 Nginx 服务,我们需要禁用主机名验证。

<b>final</b> Properties props = System.getProperties();
props.setProperty(<font>"jdk.internal.httpclient.disableHostnameVerification"</font><font>, Boolean.TRUE.toString());


在其他客户端中,这可能需要设置一个接受所有连接的 HostVerifier

HostnameVerifier allHostsValid = <b>new</b> HostnameVerifier() {
    <b>public</b> <b>boolean</b> verify(String hostname, SSLSession session) {
        <b>return</b> <b>true</b>;
    }
};

到此这篇关于利用Java实现mTLS调用的文章就介绍到这了,更多相关Java实现mTLS调用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 深入理解SpringBoot的配置环境属性

    深入理解SpringBoot的配置环境属性

    SpringBoot的配置环境属性是一种强大的工具,可以帮助我们配置和管理我们的应用程序,这篇文章主要介绍了SpringBoot的配置环境属性,需要的朋友可以参考下
    2023-07-07
  • mybatis/mybatis-plus模糊查询语句特殊字符转义拦截器的实现

    mybatis/mybatis-plus模糊查询语句特殊字符转义拦截器的实现

    在开发中,我们通常会遇到这样的情况。用户在录入信息是录入了‘%’,而在查询时无法精确匹配‘%’。究其原因,‘%’是MySQL的关键字,如果我们想要精确匹配‘%’,那么需要对其进行转义,本文就详细的介绍一下
    2021-11-11
  • Java中的 VO,BO,DO 对象命名问题小结

    Java中的 VO,BO,DO 对象命名问题小结

    本文讲解VO,BO,DO 的作用以及如何使用,分析了如何消除三者之间重复的代码,同样结合现实生活中领导配秘书来类比讲解,对Java  VO  对象命名相关知识感兴趣的朋友一起看看吧
    2024-01-01
  • Java中序列化与反序列化的特性解读

    Java中序列化与反序列化的特性解读

    这篇文章主要介绍了Java中序列化与反序列化的特性解读,当我们需要将内存中的对象持久化到磁盘,数据库中时, 当我们需要与浏览器进行交互时,当我们需要实现 RPC 时, 这个时候就需要序列化和反序列化了,需要的朋友可以参考下
    2023-08-08
  • 浅谈java8中map的新方法--replace

    浅谈java8中map的新方法--replace

    下面小编就为大家带来一篇浅谈java8中map的新方法--replace。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-10-10
  • Collection stream使用示例详解

    Collection stream使用示例详解

    这篇文章主要介绍了Collection stream使用示例,stream流几乎可以完成对集合的任意操作,映射、去重、分组、排序、过滤等
    2022-12-12
  • Java调用第三方http接口的常用方式总结

    Java调用第三方http接口的常用方式总结

    这篇文章主要介绍了Java调用第三方http接口的常用方式总结,具有很好的参考价值,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • 史上最全Java8日期时间工具类(分享)

    史上最全Java8日期时间工具类(分享)

    这篇文章主要介绍了史上最全Java8日期时间工具类(分享),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • Mybatis 连接mysql数据库底层运行的原理分析

    Mybatis 连接mysql数据库底层运行的原理分析

    这篇文章主要介绍了Mybatis 连接mysql数据库底层运行的原理分析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • springboot + vue 实现递归生成多级菜单(实例代码)

    springboot + vue 实现递归生成多级菜单(实例代码)

    这篇文章主要介绍了springboot + vue 实现递归生成多级菜单,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-12-12

最新评论