使用 Java實現mTLS呼叫
本教程展示使用 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 = "/path/to/generated/client.key.pkcs8"; String publicKeyPath = "/path/to/generated/client.crt"; final byte[] publicData = Files.readAllBytes(Path.of(publicKeyPath)); final byte[] privateData = Files.readAllBytes(Path.of(privateKeyPath)); String privateString = new String(privateData, Charset.defaultCharset()) .replace("-----BEGIN PRIVATE KEY-----", "") .replaceAll(System.lineSeparator(), "") .replace("-----END PRIVATE KEY-----", ""); byte[] encoded = Base64.getDecoder().decode(privateString); final CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); final Collection<? extends Certificate> chain = certificateFactory.generateCertificates( new ByteArrayInputStream(publicData)); Key key = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(encoded)); KeyStore clientKeyStore = KeyStore.getInstance("jks"); final char[] pwdChars = "test".toCharArray(); clientKeyStore.load(null, null); clientKeyStore.setKeyEntry("test", key, pwdChars, chain.toArray(new Certificate[0])); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509"); keyManagerFactory.init(clientKeyStore, pwdChars); |
在上面的片段中
- 我們從檔案中讀取位元組。
- 我們從公鑰建立了一個證照鏈。
- 我們使用私鑰建立了一個金鑰例項。
- 使用鏈和金鑰建立了一個金鑰庫
- 建立了一個 KeyManagerFactory
現在我們已經建立了一個 KeyManagerFactory 我們可以使用它來建立一個 SSLContext
由於使用自簽名證照,我們需要使用接受它們的 TrustManager。在此示例中,信任管理器將接受伺服器提供的所有證照。
TrustManager[] acceptAllTrustManager = { new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } public void checkClientTrusted( X509Certificate[] certs, String authType) { } public void checkServerTrusted( X509Certificate[] certs, String authType) { } } }; |
然後ssl上下文初始化。
SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(keyManagerFactory.getKeyManagers(), acceptAllTrustManager, new java.security.SecureRandom()); |
客戶端程式碼:
HttpClient client = HttpClient.newBuilder() .sslContext(sslContext) .build(); HttpRequest exactRequest = HttpRequest.newBuilder() .uri(URI.create("https://127.0.0.1")) .GET() .build(); var exactResponse = client.sendAsync(exactRequest, HttpResponse.BodyHandlers.ofString()) .join(); System.out.println(exactResponse.statusCode()); |
我們將收到一個 404 程式碼,這意味著我們的請求成功進行了 mTLS 握手。
注意:如果伺服器端是使用本地 Nginx 服務,我們需要禁用主機名驗證。
final Properties props = System.getProperties(); props.setProperty("jdk.internal.httpclient.disableHostnameVerification", Boolean.TRUE.toString()); |
在其他客戶端中,這可能需要設定一個接受所有連線的 HostVerifier。
HostnameVerifier allHostsValid = new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }; |
相關文章
- 使用JNA實現Java對C的呼叫Java
- Java實現非同步呼叫Java非同步
- 手把手教你用 Go 實現一個 mTLSGoTLS
- 教你如何用 Java 實現非同步呼叫Java非同步
- 在Java中實現遠端方法呼叫(轉)Java
- 基於OpenTelemetry實現Java微服務呼叫鏈跟蹤Java微服務
- Android 使用js呼叫JavaAndroidJSJava
- 使用LangChain4J實現Agent與Tool呼叫LangChain
- 實現呼叫API介面API
- 呼叫鏈系列(2):輕呼叫鏈實現
- 使用Java實現WebSocket通訊JavaWeb
- C++庫封裝JNI介面——實現java呼叫c++C++封裝Java
- Music Studio專案心得--JNI實現C++呼叫JAVAC++Java
- 使用併發工具實現 RPC 呼叫流量控制RPC
- java使用jolt呼叫tuxedo服務JavaUX
- 呼叫API實現錄音API
- 自己寫了個Java RMI(遠端方法呼叫)的實現案例Java
- 使用Java高速實現進度條Java
- JAVA中使用介面實現松耦合Java
- 使用resilience4j-retry實現函式呼叫重試函式
- 使用emscripten實現js直接呼叫C程式碼(emscripten的初探)JSC程式
- 使用呼叫者許可權實現Schema導向操作
- 如何使用Java呼叫商品詳情APIJavaAPI
- 實現通過COM元件方式實現java呼叫C#寫的DLL檔案的完整demo元件JavaC#
- Eureka實現微服務的呼叫微服務
- 呼叫通訊錄實現思路
- nacos實現Java和.NetCore的服務註冊和呼叫JavaNetCore
- Java大作業:AI千戀萬花(呼叫api實現)附專案)JavaAIAPI
- 使用Java實現在SQLserver中實現圖片的儲存JavaSQLServer
- Java 專案中使用 Resilience4j 實現客戶端 API 呼叫的限速/節流機制Java客戶端API
- Android JNI實現Java與C/C++互相呼叫,以及so庫的生成和呼叫(JNI方式呼叫美圖秀秀so)AndroidJavaC++
- 使用Java加密與解密實現步驟Java加密解密
- Java中使用FlatBuffers實現序列化Java
- Java中使用FlatBuffer實現序列化Java
- Java 中使用 Failsafe 實現容錯JavaAI
- Laravel 如何實現既能靜態呼叫,又能動態呼叫Laravel
- Spring Boot使用@Async實現非同步呼叫:使用Future以及定義超時Spring Boot非同步
- Istio開啟mtls請求503問題分析TLS