利用Java實(shí)現(xiàn)mTLS調(diào)用
本文將使用 Java作為客戶端 與受 mTLS 保護(hù)的服務(wù)交互。
為了對我們的 Java 客戶端進(jìn)行 ssl 配置,我們需要先設(shè)置一個(gè) SSLContext
。這簡化了事情,因?yàn)?SSLContext
可用于各種 http 客戶端。
由于我們有客戶端公鑰和私鑰,我們需要將私鑰從 PEM 格式轉(zhuǎn)換為 DER。
openssl pkcs8 -topk8 -inform PEM -outform PEM -in /path/to/generated/client.key -out /path/to/generated/client.key.pkcs8 -nocrypt
下一步是將客戶端密鑰加載到 Java 代碼中并創(chuàng)建一個(gè) 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);
在上面的片段中
- 我們從文件中讀取字節(jié)。
- 我們從公鑰創(chuàng)建了一個(gè)證書鏈。
- 我們使用私鑰創(chuàng)建了一個(gè)密鑰實(shí)例。
- 使用鏈和密鑰創(chuàng)建了一個(gè)密鑰庫
- 創(chuàng)建了一個(gè)
KeyManagerFactory
現(xiàn)在我們已經(jīng)創(chuàng)建了一個(gè) KeyManagerFactory
我們可以使用它來創(chuàng)建一個(gè) SSLContext
由于使用自簽名證書,我們需要使用接受它們的 TrustManager
。在此示例中,信任管理器將接受服務(wù)器提供的所有證書。
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());
我們將收到一個(gè) 404 代碼,這意味著我們的請求成功進(jìn)行了 mTLS 握手。
注意:如果服務(wù)器端是使用本地 Nginx 服務(wù),我們需要禁用主機(jī)名驗(yàn)證。
<b>final</b> Properties props = System.getProperties(); props.setProperty(<font>"jdk.internal.httpclient.disableHostnameVerification"</font><font>, Boolean.TRUE.toString());
在其他客戶端中,這可能需要設(shè)置一個(gè)接受所有連接的 HostVerifier
。
HostnameVerifier allHostsValid = <b>new</b> HostnameVerifier() { <b>public</b> <b>boolean</b> verify(String hostname, SSLSession session) { <b>return</b> <b>true</b>; } };
到此這篇關(guān)于利用Java實(shí)現(xiàn)mTLS調(diào)用的文章就介紹到這了,更多相關(guān)Java實(shí)現(xiàn)mTLS調(diào)用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot使用過濾器和攔截器分別實(shí)現(xiàn)REST接口簡易安全認(rèn)證示例代碼詳解
這篇文章主要介紹了Spring Boot使用過濾器和攔截器分別實(shí)現(xiàn)REST接口簡易安全認(rèn)證示例代碼,通過開發(fā)實(shí)踐,理解過濾器和攔截器的工作原理,需要的朋友可以參考下2018-06-06詳解Mybatis攔截器安全加解密MySQL數(shù)據(jù)實(shí)戰(zhàn)
本文主要介紹了Mybatis攔截器安全加解密MySQL數(shù)據(jù)實(shí)戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01關(guān)于Spring中一級緩存、二級緩存和三級緩存的那些事
Spring解決循環(huán)依賴的核心思想在于提前曝,下面這篇文章主要給大家介紹了關(guān)于Spring中一級緩存、二級緩存和三級緩存的那些事,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-02-02IDEA項(xiàng)目使用SpringBoot+MyBatis-Plus的方法
這篇文章主要介紹了IDEA項(xiàng)目使用SpringBoot+MyBatis-Plus的方法,本文分步驟通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10Java類庫BeanUtils組件使用方法及實(shí)例詳解
這篇文章主要介紹了Java類庫BeanUtils組件使用方法級實(shí)例詳解,需要的朋友可以參考下2020-02-02SpringBoot分布式文件存儲(chǔ)數(shù)據(jù)庫mongod
MongoDB是一個(gè)基于分布式文件存儲(chǔ)的NoSQL數(shù)據(jù)庫,由C++語言編寫,旨在為Web應(yīng)用提供可擴(kuò)展的高性能數(shù)據(jù)存儲(chǔ)解決方案。MongoDB是一個(gè)介于關(guān)系數(shù)據(jù)庫和非關(guān)系數(shù)據(jù)庫之間的產(chǎn)品,是非關(guān)系數(shù)據(jù)庫中功能最豐富最像關(guān)系數(shù)據(jù)庫的2023-02-02