java SSLContext創(chuàng)建方式
概述
HTTPS相對于HTTP多了SSL(security sock layer),應(yīng)用層將數(shù)據(jù)丟給TCP時,需要經(jīng)過SSL層的加密處理;TCP層的數(shù)據(jù)丟給應(yīng)用層時,需要經(jīng)過SSL層的解密處理。
因此網(wǎng)絡(luò)中傳輸?shù)亩际羌用芎蟮臄?shù)據(jù),提高的通信的安全性。
HTTPS除了擁有傳輸加密的功能,還提供身份認證,防止對端偽造身份。這個是通過HTTPS證書實現(xiàn)。
注下圖中對HTTPS握手過程進行簡化,握手過程的關(guān)鍵步驟就是證書校驗及對稱加密秘鑰的協(xié)商,另外客戶端證書的校驗是可選的。
問題
標準證書都是第三方機構(gòu)頒發(fā)的,需要付費找第三方機構(gòu)申請。有些出于節(jié)省成本或者省事的目的,一般會使用工具生成自簽名的證書。
瀏覽器訪問這種自簽名證書的網(wǎng)址時就會彈出不安全的提示,如果是java代碼訪問這種網(wǎng)址時就會拋出異常。
解決這種問題有2個途徑,一種是忽略證書認證,另一種就是將自簽名的證書添加到受信證書庫中。
SSLContext關(guān)鍵參數(shù)說明
SSLContext都是通過SSLContext.getInstance(String protocol)方法獲取,獲取后需要調(diào)用init方法初始化。
init方法簽名如下:
public final void init(KeyManager[] km, TrustManager[] tm,SecureRandom random)
KeyManager
- 用于HTTPS雙向認證時,客戶端向服務(wù)端發(fā)送的認證信息(證書);與不同的服務(wù)端交互時,客戶端可能用不同的身份(證書),所以需要KeyManager進行管理。
- 如果只是單向認證,KeyManager[]可以為空。
TrustManager
- 用于客戶端檢測服務(wù)端發(fā)送過來的證書。
KeyStore:只是單純的存儲證書、秘鑰數(shù)據(jù),不包含任何邏輯。
TrustManager,KeyManager可以使用KeyStore得到證書列表進行相應(yīng)的業(yè)務(wù)處理。
忽略證書認證
有些語言比如Python是可以修改全局配置去忽略證書檢查,但是Java好像沒有提供這種功能,所以需要覆寫證書認證的類X509TrustManager 。
忽略證書認證后,雙方通信的時候仍然是加密的,只是無法對服務(wù)端的身份進行認證,有服務(wù)端偽造的風(fēng)險。如果都是在內(nèi)網(wǎng),可以采用這種簡潔的手法。
public SSLContext buildSSLContext() throws Exception { X509TrustManager x509TrustManager = new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } }; SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); sslContext.init((KeyManager[]) null, new X509TrustManager[] {x509TrustManager}, (SecureRandom) null); return sslContext; }
將自簽名證書放到受信證書庫
將證書直接導(dǎo)入到JDK的證書庫
待續(xù)
通過編碼的方式將證書放到受信證書列表中
@Override public SSLContext buildSSLContext() throws Exception { KeyStore keyStore = buildKeyStore(); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(keyStore); SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); sslContext.init((KeyManager[]) null, tmf.getTrustManagers(), (SecureRandom) null); return sslContext; } private KeyStore buildKeyStore() throws Exception { // 獲取自簽名的證書 List<X509Certificate> certs = loadHttpsCerts(); KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null, null); TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init((KeyStore) null); // 獲得jdk證書庫中的證書 Arrays.stream(trustManagerFactory.getTrustManagers()) .filter(manager -> manager instanceof X509TrustManager) .findFirst() .ifPresent(manager -> { List<X509Certificate> jdkCerts = Arrays.asList(((X509TrustManager) manager).getAcceptedIssuers()); certs.addAll(jdkCerts); }); certs.stream().forEach(cert -> { keyStore.setCertificateEntry(cert.getSubjectDN().getName(), cert); }); return keyStore; } private List<X509Certificate> loadHttpsCerts() throws IOException, CertificateException { List<X509Certificate> certs = new ArrayList<>(32); PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); Resource[] resources = resolver.getResources(HTTPS_CERTS_PATH); for (Resource resource : resources) { InputStream inStream = resource.getInputStream(); CertificateFactory factory = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate) factory.generateCertificate(inStream); certs.add(cert); } return certs; }
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java對象以Hash結(jié)構(gòu)存入Redis詳解
這篇文章主要介紹了Java對象以Hash結(jié)構(gòu)存入Redis詳解,和Java中的對象非常相似,卻不能按照Java對象的結(jié)構(gòu)直接存儲進Redis的hash中,因為Java對象中的field是可以嵌套的,而Redis的Hash結(jié)構(gòu)不支持嵌套結(jié)構(gòu),需要的朋友可以參考下2023-08-08JAVA多線程處理for循環(huán)數(shù)據(jù)詳細講解
這篇文章主要給大家介紹了關(guān)于JAVA多線程處理for循環(huán)數(shù)據(jù)的相關(guān)資料,我們在代碼中經(jīng)常需要使用for循環(huán)這個操作來達到目的,而當for循環(huán)的次數(shù)過多時我們會發(fā)現(xiàn)執(zhí)行效率會變的很低,整體耗時非常多,需要的朋友可以參考下2023-07-07