????????http是無狀態的,https是在http應用層協議和tcp傳輸控制層之間加了一層,主要功能包括加密傳輸內容,校驗信息是否完整,信息是否被篡改等。http的網絡傳輸,源端應用層發送http請求,傳輸到源端的控制層,網絡層,物理層->到對方的物理層->網絡層->傳輸控制層->應用層,https就是在兩邊的控制層和應用層之間加了一層SSL/TLS協議層。發送時將http的明文加密,接收時解密,校驗是否完整,是否被篡改,在正確無誤的明文發送給目標端的應用層,作為http報文。
發送方:應用層http明文->SSL/TLS->秘文->控制層 接收方:控制層秘文->SSL/TLS->明文-應用層http
加密方式,分為對稱加密,非對稱加密;對稱加密,加密強度弱,耗時短,使用相同的key加解密;非對稱加密,加密強度高,耗時長,一個使用公鑰,一個使用私鑰。
tls握手流程:
步驟一:tls握手和密鑰交換(非對稱加密階段)
1.客戶端發送自己tls版本,支持的加密方式,隨機數
2.服務器回復選擇的加密方式,隨機數和證書,證書包括認證機構,服務器地址,公鑰,有效期等
3.客戶端驗證證書。查看證書的公鑰,服務器地址,過期時間ca簽名等
4.客戶端生成一個用于對數據加密的對稱密鑰,并用服務器的公鑰將這個對稱密鑰加密,傳輸給服務器
5.服務器用私鑰解密,獲取到對稱密鑰。
步驟二:數據傳輸,對稱加密階段
每次發送數據,使用對稱密鑰對數據進行加密,服務器解密后傳輸給應用層。再將引用層的響應信息加密發送給客戶端。
java發送https請求需要怎么做
1.生產環境必須使用權威CA頒發的證書,禁止信任所有證書。
2.自簽名證書僅限測試環境,生產環境使用會到安全風險。
3.導入證書到JVM信任庫
通過keytool將CA證書導入JVM默認信任庫cacerts:
keytool -import -alias server_cert -file server.crt -keystore $JAVA_HOME/lib/security/cacerts
輸入默認密碼changeit,完成后重啟應用生效。
若需要隔離應用證書,可創建獨立的信任庫:
keytool -import -alias my_ca -file ca.crt -keystore /path/to/my_truststore.jks ? #啟動時指定JVM參數: -Djavax.net.ssl.trustStore=/path/to/my_truststore.jks -Djavax.net.ssl.trustStorePassword=your_password ```[6,8](@ref)
https請求實現方式:
1.使用JAVA標準庫
import javax.net.ssl.HttpsURLConnection; import java.net.URL; import java.io.BufferedReader; import java.io.InputStreamReader; ? public class HttpsExample {public static void main(String[] args) throws Exception {URL url = new URL("https://api.example.com/data");HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();conn.setRequestMethod("GET"); ?// 驗證響應try (BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {String line;while ((line = in.readLine()) != null) {System.out.println(line);}}} }
2.使用Apache HttpClient(推薦)
#maven依賴 <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version> </dependency> import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.ssl.SSLContexts; import org.apache.http.client.methods.HttpGet; import org.apache.http.util.EntityUtils; ? public class HttpClientExample {public static void main(String[] args) throws Exception {// 加載信任庫(可選,默認使用JVM信任庫)SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, (chain, authType) -> true) // 生產環境需替換為證書驗證邏輯.build(); ?try (CloseableHttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build()) {HttpGet httpGet = new HttpGet("https://api.example.com/data");HttpResponse response = httpClient.execute(httpGet);String result = EntityUtils.toString(response.getEntity());System.out.println(result);}} }
3.使用OkHttp(高性能首選)
<dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.11.0</version> </dependency> import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; ? public class OkHttpExample {public static void main(String[] args) throws Exception {OkHttpClient client = new OkHttpClient.Builder().sslSocketFactory(sslContext.getSocketFactory(), trustManager) // 生產環境需配置真實TrustManager.build(); ?Request request = new Request.Builder().url("https://api.example.com/data").build(); ?try (Response response = client.newCall(request).execute()) {System.out.println(response.body().string());}} }
為什么客戶端需要安裝CA證書?
1.驗證服務器身份(核心作用)
-
服務器證書的合法性驗證:當客戶端(java程序)訪問HTTPS服務器時,服務器會返回它的數字證書,客戶端需要使用CA證書驗證服務器證書是否由可信結構簽發,是否被篡改,域名是否匹配等。
2.信任鏈的建立
-
證書鏈驗證:服務器證書通常由中間CA簽發,而中間CA的合法性需由根CA證書驗證。java默認信任庫(cacerts)內置了權威CA的根證書,用于逐級驗證整個證書鏈。
-
未安裝CA證書的后果:若服務器證書的簽發CA不在客戶端信任庫中,Java會拋出異常,拒接鏈接。
開發環境與生產環境為什么不同?
1.開發環境:開發測試時使用自簽名證書(非CA簽發),瀏覽器或Java默認不信任此類證書。
驗證方式:
1.忽略驗證(僅限測試):通過自定義TrustManager跳過證書檢查(高風險,生產禁用)
2.手動導入信任庫:將自簽名證書導入JVM的cacerts文件,使java臨時信任該證書。
keytool -import -alias dev_cert -file dev.crt -keystore $JAVA_HOME/lib/security/cacerts
目的:快速測試HTTPS功能,避免頻繁申請CA證書的成本。
2.生產環境:必須使用權威CA(如Let's Encrypt,DigiCert)簽發的證書,確保全局可信
驗證機制:
1.自動信任鏈驗證:依賴JVM內置的cacerts信任庫(含主流CA根證書),無需額外配置。
2.證書生命周期管理:需監控有效期,及時續期,避免服務中斷
生產環境代碼應該如何修改?
####
//替換開發代碼中的跳過驗證部分.loadTrustMaterial(null,(chain,authType)->true) KeyStore trustStore = KeyStore.getInstance("JKS"); try (InputStream is = new FileInputStream("truststore.jks")) {trustStore.load(is, "truststore_password".toCharArray()); } ? SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(trustStore, null) // 啟用信任庫驗證.build();
雙向驗證:
若需客戶端證書認證(如銀行接口):
KeyStore keyStore = KeyStore.getInstance("PKCS12"); keyStore.load(new FileInputStream("client.p12"), "client_pass".toCharArray()); ? SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(keyStore, "client_pass".toCharArray()) // 加載客戶端證書.loadTrustMaterial(trustStore, null) // 加載信任庫.build();
生產環境完整代碼示例:
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.ssl.SSLContexts; import org.apache.http.util.EntityUtils; import java.io.FileInputStream; import java.security.KeyStore;public class ProductionHttpsClient {public static void main(String[] args) throws Exception {// 1. 加載信任庫(生產環境使用CA證書)KeyStore trustStore = KeyStore.getInstance("JKS");try (InputStream is = new FileInputStream("/path/to/truststore.jks")) {trustStore.load(is, "truststore_pass".toCharArray());}// 2. 初始化SSLContext(啟用完整證書驗證)SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(trustStore, null) // 關鍵修改:啟用CA驗證.build();// 3. 創建HttpClient(使用默認域名校驗)try (CloseableHttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build()) {// 4. 發送請求HttpGet httpGet = new HttpGet("https://api.example.com/data");try (CloseableHttpResponse response = httpClient.execute(httpGet)) {String result = EntityUtils.toString(response.getEntity());System.out.println(result);}}} }
生產環境注意事項
1.證書管理
-
監控CA證書有效期,提前續期(如Let's Encrypt證書90天有效期)
-
定期更新JVM信任庫(cacerts),確保包含最新根證書。
2.協議與加密套件
-
強制使用TLSv1.2+,禁用弱算法(如SSLv3,TLSv1.0)
SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
3.異常處理
-
捕獲SSLHandshakeExceptioni并記錄詳細日志,快速定位證書問題
4.性能開銷
-
復用CloseableHttpClient實例,減少SSL握手開銷
為什么開發環境不能共用生產的根證書
1.安全漏洞放大
-
開發環境常使用自簽名證書,若將其導入生產信任庫,攻擊者可通過偽造相同域名的自簽名證書劫持通信
-
生產根證書被用于開發環境時,測試證書的泄露可能危及生產系統信任鏈
2.證書管理混亂
-
開發證書頻繁變更:測試需快速迭代,證書常重置或替換,若共用會導致生產信任庫頻繁更新,引發服務中斷
3.驗證策略沖突
-
開發環境往往需跳過嚴格驗證(如
NoopHostnameVerifier
),而生產環境必須啟用完整驗證(域名匹配、證書鏈校驗 -
共用配置會強制生產環境降低安全標準,或讓開發環境無法調試
4.合規與審計風險
-
行業標準(如 PCI DSS)要求生產環境證書必須由公共 CA 簽發并獨立管理,共用會導致審計失敗