来自Google

时间:2016-02-22 03:00:49

标签: java android android-security sslsocketfactory trustmanager

我在谷歌播放中使用了一个应用程序,我收到了来自谷歌的邮件说:

  

此电子邮件末尾列出的您的应用使用接口X509TrustManager的不安全实现。具体而言,在与远程主机建立HTTPS连接时,该实现会忽略所有SSL证书验证错误,从而使您的应用容易受到中间人攻击。

     

要正确处理SSL证书验证,请在自定义X509TrustManager接口的checkServerTrusted方法中更改代码,以便在服务器提供的证书不符合您的期望时引发CertificateException或IllegalArgumentException。

我的应用使用“https”,我的checkServerTrusted()如下:

 TrustManager tm = new X509TrustManager() {
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

        }

        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    };

然后我修改了这个功能:

 TrustManager tm = new X509TrustManager() {
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            if (chain == null) {
                throw new IllegalArgumentException("checkServerTrusted: X509Certificate array is null");
            }

            if (!(chain.length > 0)) {
                throw new IllegalArgumentException("checkServerTrusted: X509Certificate is empty");
            }

            if (!(null != authType && authType.equalsIgnoreCase("RSA"))) {

                throw new CertificateException("checkServerTrusted: AuthType is not RSA");
            }
        }

        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

自定义SSLSocketFactory:

public class MySSLSocketFactory extends SSLSocketFactory {
SSLContext sslContext = SSLContext.getInstance("TLS");

public MySSLSocketFactory(KeyStore ctx) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
    super(ctx);

    TrustManager tm = new X509TrustManager() {
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    };

    sslContext.init(null, new TrustManager[]{tm}, null);
}

@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
    return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
}

@Override
public Socket createSocket() throws IOException {
    return sslContext.getSocketFactory().createSocket();
}

}

HttpClient函数:

private static HttpClient getHttpClient(int timeout) {
    if (null == mHttpClient) {

        try {
            KeyStore trustStore = KeyStore.getInstance(KeyStore
                    .getDefaultType());
            trustStore.load(null, null);
            SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 

            HttpParams params = new BasicHttpParams();

            HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
            HttpProtocolParams.setContentCharset(params,
                    HTTP.DEFAULT_CONTENT_CHARSET);
            HttpProtocolParams.setUseExpectContinue(params, true);


            ConnManagerParams.setTimeout(params, timeout);

            HttpConnectionParams.setConnectionTimeout(params, timeout);

            HttpConnectionParams.setSoTimeout(params, timeout);


            SchemeRegistry schReg = new SchemeRegistry();
            schReg.register(new Scheme("http", PlainSocketFactory
                    .getSocketFactory(), 80));
            schReg.register(new Scheme("https", sf, 443));

            ClientConnectionManager conManager = new ThreadSafeClientConnManager(
                    params, schReg);

            mHttpClient = new DefaultHttpClient(conManager, params);
        } catch (Exception e) {
            e.printStackTrace();
            return new DefaultHttpClient();
        }
    }
    return mHttpClient;
}

但是我对此并不了解,我只是通过电子邮件说的修改我的代码,我想我还没有解决这个问题。这个警告​​到底是什么?怎么解决?

3 个答案:

答案 0 :(得分:1)

您提出的修改不会修复安全漏洞。无论有效性如何,您的代码仍将接受任何格式正确的证书。

如果您不确定如何正确验证证书,则应该删除自定义信任管理器。除非你做一些与众不同的事情,否则你不需要一个。

答案 1 :(得分:0)

最简单的方法是不提供自己的自定义TrustManager。只需使用默认的TrustManager,它将为您执行公钥( X.509 )验证和验证。

答案 2 :(得分:0)

仅使用默认的 X509trustmanager 方法 checkServerTrusted(chain, authType),它们将适当地处理所有验证。