私有云如何配置自签名证书?在 Android 9.0 及之后版本发生 SSL handshake timed out 异常怎么解决?

"描述(来源参考:https://www.rongcloud.cn/?utm_source=SEO&utm_term=jishitongxun)
本文档仅适用于私有云,且需要使用自签证书(自签名证书)绕过自签名配置的客户。

Android 9.0 及之后版本,融云 SDK 开始建立网络连接时发生 SSL handshake timed out 异常。

分析(根因分析、需求分析)
Android 9.0 开始,默认不允许明文传输,所以在建立网络连接时会使用 https 连接,同时进行安全认证。如果私有云客户未在应用内正确配置 SSL 安全认证,即会发生 SSL handshake timed out 异常。

公有云用户因为 SDK 直接使用融云内置的安全证书,一般不会遇到该问题。

解决方案
推荐使用方案一。

方案一:配置 HTTPS 使用自签证书
如果在应用里没有声明允许明文传输,那么 SDK 默认在 Android 9.0 系统上会使用 https 连接方式,也就意味着会进行安全认证。

如果 IM SDK 版本 ≧ 2.10.6.3,请在 SDK 初始化(init)之前, 调用如下方法:

注意:不要对这个方法进行进程限制, 不能只在主进程执行。因为 SDK 的业务都是在 IPC 进程操作, 所以网络操作也是在 IPC 进程。

private void setSSL() {
        SSLContext mySSLContext = getSslContext();
        if (mySSLContext != null) {
            // 设置 SDK 内部的上传下载支持自签证书
            SSLUtils.setSSLContext(mySSLContext);
            // 并且把 Glide 设置成支持自签证书(glide 内部是 HttpsURLConnection)
            // SDK 内置的图片预览用的是 Glide
            HttpsURLConnection.setDefaultSSLSocketFactory(mySSLContext.getSocketFactory());
        }
        HostnameVerifier hostnameVerifier = getHostnameVerifier();
        if (hostnameVerifier != null) {
            // 设置 SDK 内部的上传下载支持自签证书
            SSLUtils.setHostnameVerifier(hostnameVerifier);
            // 并且把 Glide 设置成支持自签证书(glide 内部是 HttpsURLConnection)
            // SDK 内置的图片预览用的是 Glide
            HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
        }
        // 设置合并转发消息自签证书
        RongConfigCenter.featureConfig().setSSLInterceptor(new FeatureConfig.SSLInterceptor() {
            @Override
            public boolean check(SslCertificate sslCertificate) {
                return true;
            }
        });
    }

    private HostnameVerifier getHostnameVerifier() {
        HostnameVerifier hostnameVerifier =
                new HostnameVerifier() {
                    @Override
                    public boolean verify(String hostname, SSLSession session) {
                        return true;
                    }
                };
        return hostnameVerifier;
    }

    private SSLContext getSslContext() {
        TrustManager tm[] = {
            new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType)
                        throws CertificateException {
                    Log.d(""checkClientTrusted"", ""authType:"" + authType);
                }

                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType)
                        throws CertificateException {
                    Log.d(""checkServerTrusted"", ""authType:"" + authType);
                }

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
            }
        };

        SSLContext mySSLContext = null;
        try {
            mySSLContext = SSLContext.getInstance(""TLS"");
            mySSLContext.init(null, tm, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return mySSLContext;
    }
如果使用的 IMLib 版本低于 2.10.6.3 版本,需要调用下面的 API , 参数传 true:

/**
 * 设置建立 Https 连接时,是否使用自签证书。
 *

此方法需要在 {@link #init(Context)}之前调用。


 *

如果不调用此方法, SDK 连接时会按默认证书处理


 *
 * @param isEnable 是否使用自`预先格式化的文本`签证书。true 使用自签证书;false, 使用默认证书。
 */
public void enableHttpsSelfCertificate(final boolean isEnable)
方案二:在应用里声明允许明文传输
风险声明:允许明文传输可能导致 Google Play 无法上架。

通过下面配置,在 Android 9.0 手机上会仍然使用 http 连接,即明文传输的方式。

在应用的 res/xml 文件夹下新建 network_security_config.xml 文件



   

在 AndroidManifest.xml 的 application 节点下,配置允许明文传输的属性。

    android:name="".myApp""
    android:allowBackup=""true""
    android:icon=""@drawable/seal_app_logo""
    android:label=""@string/app_name""
    android:networkSecurityConfig=""@xml/network_security_config""
    android:supportsRtl=""true""
    android:theme=""@style/AppTheme"">"

你可能感兴趣的:(Android,android,ssl,数据库)