您好,登錄后才能下訂單哦!
Java實現自動安裝校驗TLS/SSL證書?相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
主要實現如下功能:
1.自動檢測,校驗根證書,校驗過期時間,校驗簽名的證書是否有效,校驗證書和域名是否匹配
2.實現證書的自動存儲,自動安裝,加載
3.實現普通Socket自動升級為SSLSocket
一.實現配置類
首先,我們先添加2個配置類
package com.ssl.rx.http; import java.security.KeyStore; public class ConnectionConfiguration { /** 證書文件路徑 */ private String truststorePath; /** 證書類型 */ private String truststoreType; /** 證書文件密碼 */ private String truststorePassword; /** 是否驗證證書鏈的簽名有效性 */ private boolean verifyChainEnabled = true; /** 是否校驗根證書,注意,自簽名證書沒有根證書 */ private boolean verifyRootCAEnabled = true; /** 是否允許通過自簽名證書 */ private boolean selfSignedCertificateEnabled = false; /** 是否檢查證書的有效期 */ private boolean expiredCertificatesCheckEnabled = true; /** 檢查域名的匹配情況 */ private boolean notMatchingDomainCheckEnabled = true; private String server; private int port; public ConnectionConfiguration() { truststorePassword = "WlZSak5GcFVUbTlsVjJSNg=="; truststorePath = "socket_tls_clientTrust.cert"; truststoreType = "jks"; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public String getServer() { return server; } public void setServer(String server) { this.server = server; } public boolean isExpiredCertificatesCheckEnabled() { return expiredCertificatesCheckEnabled; } public void setSelfSignedCertificateEnabled(boolean selfSignedCertificateEnabled) { this.selfSignedCertificateEnabled = selfSignedCertificateEnabled; } public void setExpiredCertificatesCheckEnabled(boolean expiredCertificatesCheckEnabled) { this.expiredCertificatesCheckEnabled = expiredCertificatesCheckEnabled; } public boolean isSelfSignedCertificateEnabled() { return selfSignedCertificateEnabled; } public boolean isNotMatchingDomainCheckEnabled() { return notMatchingDomainCheckEnabled; } public boolean isVerifyRootCAEnabled() { return verifyRootCAEnabled; } public void setVerifyRootCAEnabled(boolean verifyRootCAEnabled) { this.verifyRootCAEnabled = verifyRootCAEnabled; } public void setVerifyChainEnabled(boolean verifyChainEnabled) { this.verifyChainEnabled = verifyChainEnabled; } public boolean isVerifyChainEnabled() { return verifyChainEnabled; } public String getTruststoreType() { return truststoreType; } public void setTruststoreType(String truststoreType) { this.truststoreType = truststoreType; } public String getTruststorePassword() { return truststorePassword; } public void setTruststorePassword(String truststorePassword) { this.truststorePassword = truststorePassword; } public String getTruststorePath() { return truststorePath; } public void setTruststorePath(String truststorePath) { this.truststorePath = truststorePath; } public void setNotMatchingDomainCheckEnabled(boolean notMatchingDomainCheckEnabled) { this.notMatchingDomainCheckEnabled = notMatchingDomainCheckEnabled; } } 然后增加一個用于存儲keystore的javaBean package com.ssl.rx.http; public class KeyStoreOptions { private final String type; private final String path; private final String password; public KeyStoreOptions(String type, String path, String password) { super(); this.type = type; this.path = path; this.password = password; } public String getType() { return type; } public String getPath() { return path; } public String getPassword() { return password; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((password == null) ? 0 : password.hashCode()); result = prime * result + ((path == null) ? 0 : path.hashCode()); result = prime * result + ((type == null) ? 0 : type.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; KeyStoreOptions other = (KeyStoreOptions) obj; if (password == null) { if (other.password != null) return false; } else if (!password.equals(other.password)) return false; if (path == null) { if (other.path != null) return false; } else if (!path.equals(other.path)) return false; if (type == null) { if (other.type != null) return false; } else if (!type.equals(other.type)) return false; return true; } }
最后,我們來實現核心部分,證書管理器
二.實現核心代碼
package com.ssl.rx.http; public class SSLX509CertificateManager { private static final Logger logger = Logger.getLogger("SSLX509CertificateManager"); private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray(); private static Pattern cnPattern = Pattern.compile("(?i)(cn=)([^,]*)"); private static Map<KeyStoreOptions, KeyStore> stores = new HashMap<KeyStoreOptions, KeyStore>(); private static String toHexString(byte[] bytes) { StringBuilder sb = new StringBuilder(bytes.length * 3); for (int b : bytes) { b &= 0xff; sb.append(HEXDIGITS[b >> 4]); sb.append(HEXDIGITS[b & 15]); sb.append(' '); } return sb.toString(); } /** * 開始握手等一系列密鑰協商 * * @param socket * @return */ public static boolean startHandshake(SSLSocket socket) { try { logger.log(Level.INFO, "-開始握手,認證服務器證書-"); socket.startHandshake(); System.out.println(); logger.log(Level.INFO, "-握手結束,結束認證服務器證書-"); } catch (SSLException e) { e.printStackTrace(); return false; } catch (IOException e) { e.printStackTrace(); return false; } return true; } public static SSLSocket createTrustCASocket(String host, int port, ConnectionConfiguration config) throws Exception { if (config == null) { config = new ConnectionConfiguration(); } KeyStore ks = getKeyStore(config); SSLContext context = SSLContext.getInstance("TLS"); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(ks); X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0]; CAX509TrustManager tm = new CAX509TrustManager(defaultTrustManager, ks, config); context.init(null, new TrustManager[] { tm }, new SecureRandom()); SSLSocketFactory factory = context.getSocketFactory(); logger.log(Level.INFO, "開始連接: " + host + ":" + port + "..."); SSLSocket socket = (SSLSocket) factory.createSocket(host, port); socket.setSoTimeout(10000); config.setServer(host); config.setPort(port); // config.setTrustKeyStore(ks); X509Certificate certificate = (X509Certificate) ks.getCertificate(host + ":" + port); if (certificate != null && isValid(certificate)) { logger.log(Level.INFO, "-證書文件存在并且有效,無需進行握手-"); return socket; } if (!startHandshake(socket)) { logger.log(Level.SEVERE, "-握手失敗-"); return null; } X509Certificate[] chain = tm.chain; if (chain == null || chain.length == 0) { logger.log(Level.SEVERE, "-證書鏈為空,認證失敗-"); return null; } if (config.isVerifyRootCAEnabled()) { boolean isValidRootCA = checkX509CertificateRootCA(ks, chain, config.isSelfSignedCertificateEnabled()); if (!isValidRootCA) { return null; } } return socket; } /** * 獲取keystore,防治多次加載 * * @param config * @return * @throws KeyStoreException * @throws IOException * @throws NoSuchAlgorithmException * @throws CertificateException * @throws FileNotFoundException */ private static KeyStore getKeyStore(ConnectionConfiguration config) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, FileNotFoundException { KeyStore ks; synchronized (stores) { KeyStoreOptions options = new KeyStoreOptions(config.getTruststoreType(), config.getTruststorePath(), config.getTruststorePassword()); if (stores.containsKey(options)) { logger.log(Level.INFO, "從緩存中獲取trustKeystore"); ks = stores.get(options); } else { File file = new File(config.getTruststorePath()); char[] password = config.getTruststorePassword().toCharArray(); logger.log(Level.INFO, "加載" + file + "證書文件"); ks = KeyStore.getInstance(KeyStore.getDefaultType()); if (!file.exists()) { logger.log(Level.INFO, "證書文件不存在,選擇自動創建"); ks.load(null, password); } else { logger.log(Level.INFO, "證書文件存在,開始加載"); InputStream in = new FileInputStream(file); ks.load(in, password); in.close(); } stores.put(options, ks); } } return ks; } public static SSLSocket createTrustCASocket(String host, int port) throws Exception { return createTrustCASocket(host, port, null); } public static SSLSocket createTrustCASocket(Socket s, ConnectionConfiguration config) throws Exception { if (config == null) { config = new ConnectionConfiguration(); } KeyStore ks = getKeyStore(config); SSLContext context = SSLContext.getInstance("TLS"); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(ks); X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0]; CAX509TrustManager tm = new CAX509TrustManager(defaultTrustManager, ks, config); context.init(null, new TrustManager[] { tm }, new SecureRandom()); SSLSocketFactory factory = context.getSocketFactory(); String host = s.getInetAddress().getHostName(); int port = s.getPort(); logger.log(Level.INFO, "開始連接: " + host + ":" + port + "..."); SSLSocket socket = (SSLSocket) factory.createSocket(s, host, port, true); socket.setSoTimeout(10000); config.setServer(s.getInetAddress().getHostName()); config.setPort(s.getPort()); X509Certificate certificate = (X509Certificate) ks.getCertificate(host + ":" + s.getPort()); if (certificate != null && isValid(certificate)) { logger.log(Level.INFO, "-證書文件存在并且有效,無需進行握手-"); return socket; } if (!startHandshake(socket)) { return null; } X509Certificate[] chain = tm.chain; if (chain == null || chain.length == 0) { logger.log(Level.SEVERE, "-證書鏈為空,認證失敗-"); return null; } if (config.isVerifyRootCAEnabled()) { boolean isValidRootCA = checkX509CertificateRootCA(ks, chain, config.isSelfSignedCertificateEnabled()); if (!isValidRootCA) { logger.log(Level.SEVERE, "根證書校驗無效"); return null; } } return socket; } public static SSLSocket createTrustCASocket(Socket s) throws Exception { return createTrustCASocket(s, null); } public static class CAX509TrustManager implements X509TrustManager { private final X509TrustManager tm; private X509Certificate[] chain; private KeyStore keyStore; private ConnectionConfiguration config; public MessageDigest sha1 = null; public MessageDigest md5 = null; public CAX509TrustManager(X509TrustManager tm, KeyStore ks, ConnectionConfiguration config) throws NoSuchAlgorithmException { this.tm = tm; this.keyStore = ks; sha1 = MessageDigest.getInstance("SHA1"); md5 = MessageDigest.getInstance("MD5"); this.config = config; } public X509Certificate[] getAcceptedIssuers() { return tm.getAcceptedIssuers(); // 生成證書數組,用于存儲新證書 } public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { tm.checkClientTrusted(chain, authType); // 檢查客戶端 } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { if (this.chain == null) { this.chain = getAcceptedIssuers(); } if (chain != null && chain.length > 0) { if (!checkX509CertificateValid(chain, config)) { logger.log(Level.SEVERE, "證書校驗未通過"); return; } for (int i = 0; i < chain.length; i++) { X509Certificate certificate = chain[i]; if (i == 0) { saveCAToKeyStore(certificate, config.getServer() + ":" + config.getPort()); } else { saveCAToKeyStore(certificate, null); } } } } public void saveCAToKeyStore(X509Certificate certificate, String aliasKey) throws CertificateEncodingException { try { X509Certificate cert = certificate; System.out.println(" Subject " + cert.getSubjectDN()); System.out.println(" Issuer " + cert.getIssuerDN()); sha1.update(cert.getEncoded()); System.out.println(" sha1 " + toHexString(sha1.digest())); md5.update(cert.getEncoded()); System.out.println(" md5 " + toHexString(md5.digest())); String alias = keyStore.getCertificateAlias(cert); if (alias == null || alias != null && !isValid(certificate)) { if (aliasKey == null || aliasKey.length() == 0) { alias = cert.getSubjectDN().getName(); } else { alias = aliasKey; logger.log(Level.INFO, "設定指定證書別名:" + alias); } keyStore.setCertificateEntry(alias, certificate); OutputStream out = new FileOutputStream(config.getTruststorePath()); keyStore.store(out, config.getTruststorePassword().toCharArray()); out.close(); chain = Arrays.copyOf(chain, chain.length + 1); chain[chain.length - 1] = certificate; logger.fine(certificate.toString()); } } catch (KeyStoreException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (CertificateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } public static boolean isValid(X509Certificate cert) { if (cert == null) { return false; } try { cert.checkValidity(); } catch (CertificateExpiredException e) { e.printStackTrace(); return false; } catch (CertificateNotYetValidException e) { e.printStackTrace(); return false; } return true; } /** * 校驗證書的有效性 * * @param chain * @param config * @return */ private static boolean checkX509CertificateValid(X509Certificate[] chain, ConnectionConfiguration config) { boolean result = true; if (config.isExpiredCertificatesCheckEnabled()) { result = result && checkX509CertificateExpired(chain); } if (config.isVerifyChainEnabled()) { result = result && checkX509CertificateChain(chain); } if (config.isNotMatchingDomainCheckEnabled()) { result = result && checkIsMatchDomain(chain, config.getServer()); } return result; } /** * 檢查是否匹配域名 * * @param x509Certificates * @param server * @return */ public static boolean checkIsMatchDomain(X509Certificate[] x509Certificates, String server) { server = server.toLowerCase(); List<String> peerIdentities = getPeerIdentity(x509Certificates[0]); if (peerIdentities.size() == 1 && peerIdentities.get(0).startsWith("*.")) { String peerIdentity = peerIdentities.get(0).replace("*.", ""); if (!server.endsWith(peerIdentity)) { return false; } } else { for (int i = 0; i < peerIdentities.size(); i++) { String peerIdentity = peerIdentities.get(i).replace("*.", ""); if (server.endsWith(peerIdentity)) { return true; } } } return false; } /** * 校驗根證書 * * @param trustStore * @param x509Certificates * @param isSelfSignedCertificate * 是否自簽名證書 * @return */ public static boolean checkX509CertificateRootCA(KeyStore trustStore, X509Certificate[] x509Certificates, boolean isSelfSignedCertificate) { List<String> peerIdentities = getPeerIdentity(x509Certificates[0]); boolean trusted = false; try { int size = x509Certificates.length; trusted = trustStore.getCertificateAlias(x509Certificates[size - 1]) != null; if (!trusted && size == 1 && isSelfSignedCertificate) { logger.log(Level.WARNING, "-強制認可自簽名證書-"); trusted = true; } } catch (KeyStoreException e) { e.printStackTrace(); } if (!trusted) { logger.log(Level.SEVERE, "-根證書簽名的網站:" + peerIdentities + "不能被信任"); } return trusted; } /** * 檢查證書是否過期 * * @param x509Certificates * @return */ public static boolean checkX509CertificateExpired(X509Certificate[] x509Certificates) { Date date = new Date(); for (int i = 0; i < x509Certificates.length; i++) { try { x509Certificates[i].checkValidity(date); } catch (GeneralSecurityException generalsecurityexception) { logger.log(Level.SEVERE, "-證書已經過期-"); return false; } } return true; } /** * 校驗證書鏈的完整性 * * @param x509Certificates * @return */ public static boolean checkX509CertificateChain(X509Certificate[] x509Certificates) { Principal principalLast = null; List<String> peerIdentities = getPeerIdentity(x509Certificates[0]); for (int i = x509Certificates.length - 1; i >= 0; i--) { X509Certificate x509certificate = x509Certificates[i]; Principal principalIssuer = x509certificate.getIssuerDN(); Principal principalSubject = x509certificate.getSubjectDN(); if (principalLast != null) { if (principalIssuer.equals(principalLast)) { try { PublicKey publickey = x509Certificates[i + 1].getPublicKey(); x509Certificates[i].verify(publickey); } catch (GeneralSecurityException generalsecurityexception) { logger.log(Level.SEVERE, "-無效的證書簽名-" + peerIdentities); return false; } } else { logger.log(Level.SEVERE, "-無效的證書簽名-" + peerIdentities); return false; } } principalLast = principalSubject; } return true; } /** * 返回所有可用的簽名方式 鍵值對 如CN=VeriSignMPKI-2-6 * * @param certificate * @return */ private static List<String> getSubjectAlternativeNames(X509Certificate certificate) { List<String> identities = new ArrayList<String>(); try { Collection<List<?>> altNames = certificate.getSubjectAlternativeNames(); if (altNames == null) { return Collections.emptyList(); } Iterator<List<?>> iterator = altNames.iterator(); do { if (!iterator.hasNext()) break; List<?> altName = iterator.next(); int size = altName.size(); if (size >= 2) { identities.add((String) altName.get(1)); } } while (true); } catch (CertificateParsingException e) { e.printStackTrace(); } return identities; } /** * 返回所有可用的簽名方式的值 * * @param certificate * @return */ public static List<String> getPeerIdentity(X509Certificate x509Certificate) { List<String> names = getSubjectAlternativeNames(x509Certificate); if (names.isEmpty()) { String name = x509Certificate.getSubjectDN().getName(); Matcher matcher = cnPattern.matcher(name); if (matcher.find()) { name = matcher.group(2); } names = new ArrayList<String>(); names.add(name); } return names; } }
三.測試代碼
public class TestX509CertManager { public static void main(String[] args) { try { SSLSocket baiduSocket = SSLX509CertificateManager.createTrustCASocket("www.baidu.com", 443); SSLSocket taobaoSocket = SSLX509CertificateManager.createTrustCASocket("www.taobao.com", 443); SSLSocket imququSocket = SSLX509CertificateManager.createTrustCASocket("imququ.com", 443); } catch (Exception e) { e.printStackTrace(); } } }
四.附加測試代碼
我們這里附加一個工具類,專門來實現Server-Side與Client-Side的SSLSocket 連接,也可以用于測試我們的上述代碼,只不過需要稍加改造。
package com.tianwt.rx.http; public class SSLTrustManager implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager ,HostnameVerifier { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; } public boolean isServerTrusted( java.security.cert.X509Certificate[] certs) { return true; } public boolean isClientTrusted( java.security.cert.X509Certificate[] certs) { return true; } public void checkServerTrusted( java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { return; } public void checkClientTrusted( java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { return; } @Override public boolean verify(String urlHostName, SSLSession session) { //允許所有主機 return true; } /** * 客戶端使用 */ public static HttpURLConnection connectTrustAllServer(String strUrl) throws Exception { return connectTrustAllServer(strUrl,null); } /** * 客戶端使用 * * @param strUrl 要訪問的地址 * @param proxy 需要經過的代理 * @return * @throws Exception */ public static HttpURLConnection connectTrustAllServer(String strUrl,Proxy proxy) throws Exception { javax.net.ssl.TrustManager[] trustCertsmanager = new javax.net.ssl.TrustManager[1]; javax.net.ssl.TrustManager tm = new SSLTrustManager(); trustCertsmanager[0] = tm; javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext .getInstance("TLS"); sc.init(null, trustCertsmanager, null); javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc .getSocketFactory()); HttpsURLConnection.setDefaultHostnameVerifier((HostnameVerifier) tm); URL url = new URL(strUrl); HttpURLConnection urlConn = null; if(proxy==null) { urlConn = (HttpURLConnection) url.openConnection(); }else{ urlConn = (HttpURLConnection) url.openConnection(proxy); } urlConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36"); return urlConn; } /** * 用于雙向認證,客戶端使用 * * @param strUrl * @param proxy * @return * @throws KeyStoreException * @throws NoSuchAlgorithmException * @throws CertificateException * @throws FileNotFoundException * @throws IOException * @throws UnrecoverableKeyException * @throws KeyManagementException */ public static HttpURLConnection connectProxyTrustCA(String strUrl,Proxy proxy) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException, KeyManagementException { HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String s, SSLSession sslsession) { return true; } }); String clientKeyStoreFile = "D:/JDK8Home/tianwt/sslClientKeys"; String clientKeyStorePwd = "123456"; String catServerKeyPwd = "123456"; String serverTrustKeyStoreFile = "D:/JDK8Home/tianwt/sslClientTrust"; String serverTrustKeyStorePwd = "123456"; KeyStore serverKeyStore = KeyStore.getInstance("JKS"); serverKeyStore.load(new FileInputStream(clientKeyStoreFile), clientKeyStorePwd.toCharArray()); KeyStore serverTrustKeyStore = KeyStore.getInstance("JKS"); serverTrustKeyStore.load(new FileInputStream(serverTrustKeyStoreFile), serverTrustKeyStorePwd.toCharArray()); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(serverKeyStore, catServerKeyPwd.toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(serverTrustKeyStore); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); URL url = new URL(strUrl); HttpURLConnection httpURLConnection = null; if(proxy==null) { httpURLConnection = (HttpURLConnection) url.openConnection(); }else{ httpURLConnection = (HttpURLConnection) url.openConnection(proxy); } httpURLConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36"); return httpURLConnection; } /** * 用于單向認證,客戶端使用 * * server側只需要自己的keystore文件,不需要truststore文件 * client側不需要自己的keystore文件,只需要truststore文件(其中包含server的公鑰)。 * 此外server側需要在創建SSLServerSocket之后設定不需要客戶端證書:setNeedClientAuth(false) * @param strUrl * @param proxy * @return * @throws KeyStoreException * @throws NoSuchAlgorithmException * @throws CertificateException * @throws FileNotFoundException * @throws IOException * @throws UnrecoverableKeyException * @throws KeyManagementException */ public static HttpURLConnection connectProxyTrustCA2(String strUrl,Proxy proxy) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException, KeyManagementException { HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String s, SSLSession sslsession) { return true; } }); String serverTrustKeyStoreFile = "D:/JDK8Home/tianwt/sslClientTrust"; String serverTrustKeyStorePwd = "123456"; KeyStore serverTrustKeyStore = KeyStore.getInstance("JKS"); serverTrustKeyStore.load(new FileInputStream(serverTrustKeyStoreFile), serverTrustKeyStorePwd.toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(serverTrustKeyStore); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, tmf.getTrustManagers(), null); HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); URL url = new URL(strUrl); HttpURLConnection httpURLConnection = null; if(proxy==null) { httpURLConnection = (HttpURLConnection) url.openConnection(); }else{ httpURLConnection = (HttpURLConnection) url.openConnection(proxy); } httpURLConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36"); return httpURLConnection; } /** * 用于雙向認證 * @param socketClient 是否產生socket * @return * @throws KeyStoreException * @throws NoSuchAlgorithmException * @throws CertificateException * @throws FileNotFoundException * @throws IOException * @throws UnrecoverableKeyException * @throws KeyManagementException */ public SSLSocket createTlsConnect(Socket socketClient) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException, KeyManagementException { String protocol = "TLS"; String serverKey = "D:/JDK8Home/tianwt/sslServerKeys"; String serverTrust = "D:/JDK8Home/tianwt/sslServerTrust"; String serverKeyPwd = "123456"; //私鑰密碼 String serverTrustPwd = "123456"; //信任證書密碼 String serverKeyStorePwd = "123456"; // keystore存儲密碼 KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(new FileInputStream(serverKey),serverKeyPwd.toCharArray()); KeyStore tks = KeyStore.getInstance("JKS"); tks.load(new FileInputStream(serverTrust), serverTrustPwd.toCharArray()); KeyManagerFactory km = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); km.init(keyStore, serverKeyStorePwd.toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(tks); SSLContext sslContext = SSLContext.getInstance(protocol); sslContext.init(km.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom()); //第一項是用來做服務器驗證的 SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); SSLSocket clientSSLSocket = (SSLSocket) sslSocketFactory.createSocket(socketClient,socketClient.getInetAddress().getHostAddress(),socketClient.getPort(), true); clientSSLSocket.setNeedClientAuth(false); clientSSLSocket.setUseClientMode(false); return clientSSLSocket; } /** * 用于單向認證 * server側只需要自己的keystore文件,不需要truststore文件 * client側不需要自己的keystore文件,只需要truststore文件(其中包含server的公鑰)。 * 此外server側需要在創建SSLServerSocket之后設定不需要客戶端證書:setNeedClientAuth(false) * @param socketClient * @return * @throws KeyStoreException * @throws NoSuchAlgorithmException * @throws CertificateException * @throws FileNotFoundException * @throws IOException * @throws UnrecoverableKeyException * @throws KeyManagementException */ public static SSLSocket createTlsConnect2(Socket socketClient) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, UnrecoverableKeyException, KeyManagementException { String protocol = "TLS"; String serverKey = "D:/JDK8Home/tianwt/sslServerKeys"; String serverKeyPwd = "123456"; //私鑰密碼 String serverKeyStorePwd = "123456"; // keystore存儲密碼 KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(new FileInputStream(serverKey),serverKeyPwd.toCharArray()); KeyManagerFactory km = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); km.init(keyStore, serverKeyStorePwd.toCharArray()); SSLContext sslContext = SSLContext.getInstance(protocol); sslContext.init(km.getKeyManagers(), null, new SecureRandom()); //第一項是用來做服務器驗證的 SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); SSLSocket clientSSLSocket = (SSLSocket) sslSocketFactory.createSocket(socketClient,socketClient.getInetAddress().getHostAddress(),socketClient.getPort(), true); clientSSLSocket.setNeedClientAuth(false); clientSSLSocket.setUseClientMode(false); return clientSSLSocket; } /** * 將普通的socket轉為sslsocket,客戶端和服務端均可使用 * * 服務端使用的時候是把普通的socket轉為sslsocket,并且作為服務器套接字(注意:指的不是ServerSocket,當然ServerSocket的本質也是普通socket) * * @param remoteHost * @param isClient * @return */ public static SSLSocket getTlsTrustAllSocket(Socket remoteHost,boolean isClient) { SSLSocket remoteSSLSocket = null; SSLContext context = SSLTrustManager.getTrustAllSSLContext(isClient); try { remoteSSLSocket = (SSLSocket) context.getSocketFactory().createSocket(remoteHost, remoteHost.getInetAddress().getHostName(),remoteHost.getPort(), true); remoteSSLSocket.setTcpNoDelay(true); remoteSSLSocket.setSoTimeout(5000); remoteSSLSocket.setNeedClientAuth(false); //這里設置為true時會強制握手 remoteSSLSocket.setUseClientMode(isClient); //注意服務器和客戶的角色選擇 } catch (IOException e) { e.printStackTrace(); } return remoteSSLSocket; } /** * 用于客戶端,通過所有證書驗證 * @param isClient 是否生成客戶端SSLContext,否則生成服務端SSLContext * @return */ public static SSLContext getTrustAllSSLContext(boolean isClient) { String protocol = "TLS"; javax.net.ssl.SSLContext sc = null; try { javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1]; javax.net.ssl.TrustManager tm = new SSLTrustManager(); trustAllCerts[0] = tm; sc = javax.net.ssl.SSLContext .getInstance(protocol); if(isClient) { sc.init(null, trustAllCerts, null); //作為客戶端使用 } else { String serverKeyPath = "D:/JDK8Home/tianwt/sslServerKeys"; String serverKeyPwd = "123456"; //私鑰密碼 String serverKeyStorePwd = "123456"; // keystore存儲密碼 KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(new FileInputStream(serverKeyPath),serverKeyPwd.toCharArray()); KeyManagerFactory km = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); km.init(keyStore, serverKeyStorePwd.toCharArray()); KeyManager[] keyManagers = km.getKeyManagers(); keyManagers = Arrays.copyOf(keyManagers, keyManagers.length+1); sc.init(keyManagers, null, new SecureRandom()); } } catch (KeyManagementException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnrecoverableKeyException e) { e.printStackTrace(); } catch (KeyStoreException e) { e.printStackTrace(); } catch (CertificateException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return sc; } }
看完上述內容,你們掌握Java實現自動安裝校驗TLS/SSL證書的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。