WebObjects/Web 服务/如何信任任何 SSL 证书
外观
有时,放宽 Java 安全管理器以允许连接到使用自签名证书的安全 HTTP 服务器会很有用,尤其是在开发阶段。为了避免 Java 在 HTTPS 连接上出现异常,可以使用 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.ssl
package. * * @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.ssl
package. * * @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 /** * Returntrue
if the protocol handler propertyjava. * protocol.handler.pkgs
is set to the Sun'scom.sun.net.ssl. * internal.www.protocol
deprecated one,false
* otherwise. * * @returntrue
if 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. * ssl
package. * * @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 thetrue
boolean 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 *chain
peer certificate chain. * * @param chain the peer certificate chain. * @return thetrue
boolean value * indicating the chain is trusted. */ public boolean isClientTrusted(X509Certificate[] chain) { return(true); } // checkClientTrusted /** * Always returntrue
, trusting for server SSL *chain
peer certificate chain. * * @param chain the peer certificate chain. * @return thetrue
boolean 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 thetrue
boolean 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 SSLchain
peer certificate * chain with anyauthType
authentication 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 SSLchain
peer certificate * chain with anyauthType
exchange 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