WebObjects/Web 服務/如何信任任何 SSL 證書
外觀
有時,放寬 Java 安全管理器以允許連線到使用自簽名證書的安全 HTTP 伺服器會很有用,尤其是在開發階段。為了避免在 HTTPS 連線上出現 Java 異常,可以使用 Java 金鑰庫命令列工具將自簽名證書新增到 Java 可信 X509 證書庫中
% cd /Library/Java/Home/lib/security % sudo keytool -import -keystore cacerts -alias anAlias -file aCertificate
(“cacerts”金鑰庫的預設密碼為“changeit”)
但這可能很麻煩,尤其是在應用程式必須使用各種使用自簽名或定義不當的證書的伺服器進行測試時。如果伺服器使用與用於測試它的主機名不同的主機名來使用證書,它仍然會失敗。
也可以在 Java 程式碼中更改 TrustManager? 和 HostnameVerifier?,但 API 從 JDK 1.3 和 1.4 開始發生變化。不幸的是,舊的已棄用“com.sun.net.ssl”仍然可用,這使得設定自定義 TrustManager? 和 HostnameVerifier? 有點困難。
因此,我建立了一個實用程式類,它允許放寬 SSL 信任規則。只需將其新增到包、應用程式或框架中,然後呼叫
- SSLUtilities.trustAllHostnames() 以關閉 HTTPS 連線上的預設主機名驗證;
- SSLUtilities.trustAllHttpsCertificates() 以關閉 HTTPS 連線上的預設證書驗證。
import java.security.GeneralSecurityException; import java.security.SecureRandom; import java.security.cert.X509Certificate; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; /** * This class provide various static methods that relax X509 certificate and * hostname verification while using the SSL over the HTTP protocol. * * @author Francis Labrie */ public final class SSLUtilities { /** * Hostname verifier for the Sun's deprecated API. * * @deprecated see {@link #_hostnameVerifier}. */ private static com.sun.net.ssl.HostnameVerifier __hostnameVerifier; /** * Thrust managers for the Sun's deprecated API. * * @deprecated see {@link #_trustManagers}. */ private static com.sun.net.ssl.TrustManager[] __trustManagers; /** * Hostname verifier. */ private static HostnameVerifier _hostnameVerifier; /** * Thrust managers. */ private static TrustManager[] _trustManagers; /** * Set the default Hostname Verifier to an instance of a fake class that * trust all hostnames. This method uses the old deprecated API from the *com.sun.sslpackage. * * @deprecated see {@link #_trustAllHostnames()}. */ private static void __trustAllHostnames() { // Create a trust manager that does not validate certificate chains if(__hostnameVerifier == null) { __hostnameVerifier = new _FakeHostnameVerifier(); } // if // Install the all-trusting host name verifier com.sun.net.ssl.HttpsURLConnection. setDefaultHostnameVerifier(__hostnameVerifier); } // __trustAllHttpsCertificates /** * Set the default X509 Trust Manager to an instance of a fake class that * trust all certificates, even the self-signed ones. This method uses the * old deprecated API from thecom.sun.sslpackage. * * @deprecated see {@link #_trustAllHttpsCertificates()}. */ private static void __trustAllHttpsCertificates() { com.sun.net.ssl.SSLContext context; // Create a trust manager that does not validate certificate chains if(__trustManagers == null) { __trustManagers = new com.sun.net.ssl.TrustManager[] {new _FakeX509TrustManager()}; } // if // Install the all-trusting trust manager try { context = com.sun.net.ssl.SSLContext.getInstance("SSL"); context.init(null, __trustManagers, new SecureRandom()); } catch(GeneralSecurityException gse) { throw new IllegalStateException(gse.getMessage()); } // catch com.sun.net.ssl.HttpsURLConnection. setDefaultSSLSocketFactory(context.getSocketFactory()); } // __trustAllHttpsCertificates /** * Returntrueif the protocol handler propertyjava. * protocol.handler.pkgsis set to the Sun'scom.sun.net.ssl. * internal.www.protocoldeprecated one,false* otherwise. * * @returntrueif the protocol handler * property is set to the Sun's deprecated one,false* otherwise. */ private static boolean isDeprecatedSSLProtocol() { return("com.sun.net.ssl.internal.www.protocol".equals(System. getProperty("java.protocol.handler.pkgs"))); } // isDeprecatedSSLProtocol /** * Set the default Hostname Verifier to an instance of a fake class that * trust all hostnames. */ private static void _trustAllHostnames() { // Create a trust manager that does not validate certificate chains if(_hostnameVerifier == null) { _hostnameVerifier = new FakeHostnameVerifier(); } // if // Install the all-trusting host name verifier: HttpsURLConnection.setDefaultHostnameVerifier(_hostnameVerifier); } // _trustAllHttpsCertificates /** * Set the default X509 Trust Manager to an instance of a fake class that * trust all certificates, even the self-signed ones. */ private static void _trustAllHttpsCertificates() { SSLContext context; // Create a trust manager that does not validate certificate chains if(_trustManagers == null) { _trustManagers = new TrustManager[] {new FakeX509TrustManager()}; } // if // Install the all-trusting trust manager: try { context = SSLContext.getInstance("SSL"); context.init(null, _trustManagers, new SecureRandom()); } catch(GeneralSecurityException gse) { throw new IllegalStateException(gse.getMessage()); } // catch HttpsURLConnection.setDefaultSSLSocketFactory(context. getSocketFactory()); } // _trustAllHttpsCertificates /** * Set the default Hostname Verifier to an instance of a fake class that * trust all hostnames. */ public static void trustAllHostnames() { // Is the deprecated protocol setted? if(isDeprecatedSSLProtocol()) { __trustAllHostnames(); } else { _trustAllHostnames(); } // else } // trustAllHostnames /** * Set the default X509 Trust Manager to an instance of a fake class that * trust all certificates, even the self-signed ones. */ public static void trustAllHttpsCertificates() { // Is the deprecated protocol setted? if(isDeprecatedSSLProtocol()) { __trustAllHttpsCertificates(); } else { _trustAllHttpsCertificates(); } // else } // trustAllHttpsCertificates /** * This class implements a fake hostname verificator, trusting any host * name. This class uses the old deprecated API from thecom.sun. * sslpackage. * * @author Francis Labrie * * @deprecated see {@link SSLUtilities.FakeHostnameVerifier}. */ public static class _FakeHostnameVerifier implements com.sun.net.ssl.HostnameVerifier { /** * Always returntrue, indicating that the host name is an * acceptable match with the server's authentication scheme. * * @param hostname the host name. * @param session the SSL session used on the connection to * host. * @return thetrueboolean value * indicating the host name is trusted. */ public boolean verify(String hostname, String session) { return(true); } // verify } // _FakeHostnameVerifier /** * This class allow any X509 certificates to be used to authenticate the * remote side of a secure socket, including self-signed certificates. This * class uses the old deprecated API from thecom.sun.ssl* package. * * @author Francis Labrie * * @deprecated see {@link SSLUtilities.FakeX509TrustManager}. */ public static class _FakeX509TrustManager implements com.sun.net.ssl.X509TrustManager { /** * Empty array of certificate authority certificates. */ private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {}; /** * Always returntrue, trusting for client SSL *chainpeer certificate chain. * * @param chain the peer certificate chain. * @return thetrueboolean value * indicating the chain is trusted. */ public boolean isClientTrusted(X509Certificate[] chain) { return(true); } // checkClientTrusted /** * Always returntrue, trusting for server SSL *chainpeer certificate chain. * * @param chain the peer certificate chain. * @return thetrueboolean value * indicating the chain is trusted. */ public boolean isServerTrusted(X509Certificate[] chain) { return(true); } // checkServerTrusted /** * Return an empty array of certificate authority certificates which * are trusted for authenticating peers. * * @return a empty array of issuer certificates. */ public X509Certificate[] getAcceptedIssuers() { return(_AcceptedIssuers); } // getAcceptedIssuers } // _FakeX509TrustManager /** * This class implements a fake hostname verificator, trusting any host * name. * * @author Francis Labrie */ public static class FakeHostnameVerifier implements HostnameVerifier { /** * Always returntrue, indicating that the host name is * an acceptable match with the server's authentication scheme. * * @param hostname the host name. * @param session the SSL session used on the connection to * host. * @return thetrueboolean value * indicating the host name is trusted. */ public boolean verify(String hostname, javax.net.ssl.SSLSession session) { return(true); } // verify } // FakeHostnameVerifier /** * This class allow any X509 certificates to be used to authenticate the * remote side of a secure socket, including self-signed certificates. * * @author Francis Labrie */ public static class FakeX509TrustManager implements X509TrustManager { /** * Empty array of certificate authority certificates. */ private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {}; /** * Always trust for client SSLchainpeer certificate * chain with anyauthTypeauthentication types. * * @param chain the peer certificate chain. * @param authType the authentication type based on the client * certificate. */ public void checkClientTrusted(X509Certificate[] chain, String authType) { } // checkClientTrusted /** * Always trust for server SSLchainpeer certificate * chain with anyauthTypeexchange algorithm types. * * @param chain the peer certificate chain. * @param authType the key exchange algorithm used. */ public void checkServerTrusted(X509Certificate[] chain, String authType) { } // checkServerTrusted /** * Return an empty array of certificate authority certificates which * are trusted for authenticating peers. * * @return a empty array of issuer certificates. */ public X509Certificate[] getAcceptedIssuers() { return(_AcceptedIssuers); } // getAcceptedIssuers } // FakeX509TrustManager } // SSLUtilities