利用Java實(shí)現(xiàn)mTLS調(diào)用
本文將使用 Java作為客戶端 與受 mTLS 保護(hù)的服務(wù)交互。
為了對(duì)我們的 Java 客戶端進(jìn)行 ssl 配置,我們需要先設(shè)置一個(gè) SSLContext。這簡(jiǎn)化了事情,因?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è)證書(shū)鏈。
- 我們使用私鑰創(chuàng)建了一個(gè)密鑰實(shí)例。
- 使用鏈和密鑰創(chuàng)建了一個(gè)密鑰庫(kù)
- 創(chuàng)建了一個(gè)
KeyManagerFactory
現(xiàn)在我們已經(jīng)創(chuàng)建了一個(gè) KeyManagerFactory 我們可以使用它來(lái)創(chuàng)建一個(gè) SSLContext
由于使用自簽名證書(shū),我們需要使用接受它們的 TrustManager。在此示例中,信任管理器將接受服務(wù)器提供的所有證書(shū)。
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 代碼,這意味著我們的請(qǐng)求成功進(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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mybatis/mybatis-plus模糊查詢語(yǔ)句特殊字符轉(zhuǎn)義攔截器的實(shí)現(xiàn)
在開(kāi)發(fā)中,我們通常會(huì)遇到這樣的情況。用戶在錄入信息是錄入了‘%’,而在查詢時(shí)無(wú)法精確匹配‘%’。究其原因,‘%’是MySQL的關(guān)鍵字,如果我們想要精確匹配‘%’,那么需要對(duì)其進(jìn)行轉(zhuǎn)義,本文就詳細(xì)的介紹一下2021-11-11
Java中的 VO,BO,DO 對(duì)象命名問(wèn)題小結(jié)
本文講解VO,BO,DO 的作用以及如何使用,分析了如何消除三者之間重復(fù)的代碼,同樣結(jié)合現(xiàn)實(shí)生活中領(lǐng)導(dǎo)配秘書(shū)來(lái)類(lèi)比講解,對(duì)Java VO 對(duì)象命名相關(guān)知識(shí)感興趣的朋友一起看看吧2024-01-01
Java調(diào)用第三方http接口的常用方式總結(jié)
這篇文章主要介紹了Java調(diào)用第三方http接口的常用方式總結(jié),具有很好的參考價(jià)值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
史上最全Java8日期時(shí)間工具類(lèi)(分享)
這篇文章主要介紹了史上最全Java8日期時(shí)間工具類(lèi)(分享),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
Mybatis?連接mysql數(shù)據(jù)庫(kù)底層運(yùn)行的原理分析
這篇文章主要介紹了Mybatis?連接mysql數(shù)據(jù)庫(kù)底層運(yùn)行的原理分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
springboot + vue 實(shí)現(xiàn)遞歸生成多級(jí)菜單(實(shí)例代碼)
這篇文章主要介紹了springboot + vue 實(shí)現(xiàn)遞歸生成多級(jí)菜單,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-12-12

