本文將使用 Java作為客戶端 與受 mTLS 保護的服務交互。
為了對我們的 Java 客戶端進行 ssl 配置,我們需要先設置一個 SSLContext
。這簡化了事情,因為 SSLContext
可用于各種 http 客戶端。
由于我們有客戶端公鑰和私鑰,我們需要將私鑰從 PEM 格式轉換為 DER。
1
|
openssl pkcs8 -topk8 -inform PEM -outform PEM -in /path/to/generated/client.key -out /path/to/generated/client.key.pkcs8 -nocrypt |
下一步是將客戶端密鑰加載到 Java 代碼中并創建一個 KeyManagerFactory:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
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
。在此示例中,信任管理器將接受服務器提供的所有證書。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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上下文初始化。
1
2
|
SSLContext sslContext = SSLContext.getInstance(<font> "TLS" </font><font>); sslContext.init(keyManagerFactory.getKeyManagers(), acceptAllTrustManager, <b> new </b> java.security.SecureRandom()); |
客戶端代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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 服務,我們需要禁用主機名驗證。
1
2
|
<b> final </b> Properties props = System.getProperties(); props.setProperty(<font> "jdk.internal.httpclient.disableHostnameVerification" </font><font>, Boolean.TRUE.toString()); |
在其他客戶端中,這可能需要設置一個接受所有連接的 HostVerifier
。
1
2
3
4
5
|
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調用內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://www.jdon.com/57481