如何以正确的方式处理 SSL 认证验证?

How to Handle SSL certification validation in proper way?

您好,我的应用程序是实时的,它正在使用 "https" 协议。 Google Play Team 抛出如下警告。

"Your app(s) listed at the end of this email use an unsafe implementation of the interface X509TrustManager. Specifically, the implementation ignores all SSL certificate validation errors when establishing an HTTPS connection to a remote host, thereby making your app vulnerable to man-in-the-middle attacks. An attacker could read transmitted data (such as login credentials) and even change the data transmitted on the HTTPS connection. If you have more than 20 affected apps in your account, please check the Developer Console for a full list.

To properly handle SSL certificate validation, change your code in the checkServerTrusted method of your custom X509TrustManager interface to raise either CertificateException or IllegalArgumentException whenever the certificate presented by the server does not meet your expectations. Google Play will block publishing of any new apps or updates containing the unsafe implementation of the interface X509TrustManager."

在我的项目中,我使用自定义的 http 客户端来处理 HTTPS 而不是默认的 httpClient。我的代码如下。

    public static HttpClient getNewHttpClient() {
            try
            {
                KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                trustStore.load(null, null);

                MySSLSocketFactory 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.UTF_8);

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

                ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

                return new DefaultHttpClient(ccm, params);
            }
            catch (Exception e)
            {
                return new DefaultHttpClient();
            }
        }

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

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

            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();
        }
    }

如何克服这个问题? 希望得到满意的答复。

既然您已经发布了相关代码,那么很难看出您不理解引用消息的哪一部分。

解决方法就是删除代码的TrustManager部分,根和分支,并使用默认的,然后处理可能出现的任何问题然后以 正确的 方式出现,通过调整信任库的内容,同时信任所有您需要信任但默认情况下尚未信任的证书。如果有,不应该有。

为什么需要自定义 SSLSocketFactory。您可以使用 DefaultHttpClient ,这将默认处理所有 https。仅供参考,HttpClient 已弃用并使用 HttpURLConnection.