【问题标题】:How to Handle SSL certification validation in proper way?如何以正确的方式处理 SSL 认证验证?
【发布时间】:2016-06-20 13:37:54
【问题描述】:

您好,我的应用程序已上线,并且正在使用“https”协议。 Google Play 团队发出如下警告。

“您在这封电子邮件末尾列出的应用程序使用了不安全的 接口 X509TrustManager 的实现。具体来说, 实现时忽略所有 SSL 证书验证错误 建立到远程主机的 HTTPS 连接,从而使您的 应用程序容易受到中间人攻击。攻击者可以读取 传输的数据(例如登录凭据)甚至更改数据 在 HTTPS 连接上传输。如果您有超过 20 个受影响的 您帐户中的应用程序,请查看开发者控制台以获取完整的 列表。

要正确处理 SSL 证书验证,请在 自定义 X509TrustManager 接口的 checkServerTrusted 方法 无论何时引发 CertificateException 或 IllegalArgumentException 服务器提供的证书不符合您的要求 期望。 Google Play 将阻止发布任何新应用或 包含接口的不安全实现的更新 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();
        }
    }

如何解决这个问题? 希望得到有利的答案。

【问题讨论】:

  • 你用的是webview吗?
  • 没有。我正在从 https 链接获得网络服务响应。
  • 对于通过 HTTPS 进行的交易,您是否有任何代码可以执行此电子邮件所建议的操作?它被认为是不安全的,有时是由开发人员意外添加的。
  • @DougStevenson 或者,我怀疑更常见的只是“仅用于测试”。考虑到这些不安全的TrustManagers 可能如何将不安全的应用程序投入生产,这真是令人恐惧。很高兴 Google 正在努力检测它们。

标签: android ssl android-security trustmanager


【解决方案1】:

既然已经贴出了相关代码,就很难看出引用的信息有哪些部分你不明白。

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

【讨论】:

  • 如果我要从我的代码中删除 TrustManager 部分,那么我该如何处理 HTTPS 服务器请求。实际上我正在使用 HTTPS 网络服务在服务器上发布数据。
  • 当我发布答案时,我确实希望它能够被阅读到第二段的前半句之外。
  • 是的,我刚刚删除了代码的 TrustManager 部分并实现了 HttpURLConnection 而不是 DefaullHttpClient。
【解决方案2】:

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

【讨论】:

  • 黑体字已经够了。对代码文本使用代码格式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-15
  • 1970-01-01
  • 2017-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多