java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java实现mTLS调用

利用Java实现mTLS调用

作者: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 我们可以使用它来创建一个 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调用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文