SSLSocketFactory忽略服务器证书

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SSLSocketFactory忽略服务器证书相关的知识,希望对你有一定的参考价值。

我需要创建一个建立TLS连接的javax.net.ssl.SSLSocketFactory,但忽略服务器证书的验证。不适用于HTTP协议。我知道这不是正确的事,但我需要它。我不想要或不喜欢它。

我做了一个有效的实现,但验证服务器证书(因为它假设是)实现看起来如下:

/**
     * Provide a quick method to construct a SSLSocketFactory which is a TCP socket using TLS/SSL
     * @param trustStore location of the trust store
     * @param keyStore location of the key store
     * @param trustStorePassword password to access the trust store
     * @param keyStorePassword password to access the key store
     * @return the SSLSocketFactory to create secure sockets with the provided certificates infrastructure
     * @exception java.lang.Exception in case of something wrong happens
     * */
    static public SSLSocketFactory getSocketFactory ( final String trustStore, final String keyStore, final String trustStorePassword, final String keyStorePassword) throws Exception
    {

        // todo check if the CA needs or can use the password
        final FileInputStream trustStoreStream = new FileInputStream(trustStore);
        final FileInputStream keyStoreStream = new FileInputStream(keyStore);
        // CA certificate is used to authenticate server
        final KeyStore caKs = KeyStore.getInstance("JKS");
        caKs.load(trustStoreStream, trustStorePassword.toCharArray());
        final TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
        tmf.init(caKs);

        trustStoreStream.close();

        // client key and certificates are sent to server so it can authenticate us
        final KeyStore ks = KeyStore.getInstance("JKS");
        ks.load(keyStoreStream, keyStorePassword.toCharArray());
        final KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX");
        kmf.init(ks, keyStorePassword.toCharArray());

        keyStoreStream.close();

        // finally, create SSL socket factory
        final SSLContext context = SSLContext.getInstance("TLSv1.2");
        context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

        return context.getSocketFactory();
    }
答案

我使用hack来阻止证书的验证,但它为每个SSL连接执行此操作:

public class SSLHack {private static final Logger LOG = Logger.getLogger(SSLHack.class);

public static void disableSslVerification() {
    try {
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }

            public void checkClientTrusted(X509Certificate[] certs,
                    String authType) {
            }

            public void checkServerTrusted(X509Certificate[] certs,
                    String authType) {
            }
        } };

        // Install the all-trusting trust manager
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection
                .setDefaultSSLSocketFactory(sc.getSocketFactory());

        // Create all-trusting host name verifier
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };

        // Install the all-trusting host verifier
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
    } catch (NoSuchAlgorithmException e) {
        LOG.error(e.getMessage(), e);
    } catch (KeyManagementException e) {
        LOG.error(e.getMessage(), e);
    }
}
另一答案

解决方案是创建一个虚拟的X509TrustManager类,它基本上接受所有服务器证书而不进行检查。

然后创建一个实例并将其作为SSLContext::init调用中的第二个参数传递。

但说真的,这是一个坏主意。如果您不打算检查CERT,那么使用SSL是没有意义的或更糟糕的。


1 - 这是我的理论。您的安全人员告诉您,在不安全的通道上使用MTTQ是危险的。或者他们已经阻止了端口1883.但是你有一个MTTQ / SSL服务器,你不能为获得适当的CERT而烦恼。所以你只是想把“工作”的东西放在一起。你猜怎么着。如果告诉你使用SSL的人发现,他们会have your guts for garters!如果你因为这个原因没有这样做,那么......好吧......你在做什么是没有意义的。即使是自签名服务器CERT也比这更好。您只需将其作为受信任的证书添加到客户端密钥库中。

以上是关于SSLSocketFactory忽略服务器证书的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式访问 java 密钥库以创建 SSLSocketFactory

OkHttp使用https,忽略证书验证

现在 SSLSocketFactory 在 Android 上已被弃用,处理客户端证书身份验证的最佳方法是啥?

如何正确设置 Spring Security 以使其使用提供的 SSLSocketFactory

androidOkhttp3信任所有证书设置

androidOkhttp3信任所有证书设置