运行时下载的自签名证书的 Android N 网络安全配置

shy*_*002 6 security https android ssl-certificate android-7.0-nougat

在 Android N 的 SSL 证书中,我必须添加此代码(根据给定的Android 开发人员链接

 <?xml version="1.0" encoding="utf-8"?>
 <manifest ... >
<application android:networkSecurityConfig="@xml/network_security_config"
                ... >
    ...
</application>
Run Code Online (Sandbox Code Playgroud)

以及 xml 文件夹中的文件 network_security_config.xml -

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
    <domain includeSubdomains="true">example.com</domain>
    <trust-anchors>
        <certificates src="@raw/my_ca"/>
    </trust-anchors>
</domain-config>
Run Code Online (Sandbox Code Playgroud)

这对于一个静态域来说工作得很好,但我的问题是——服务器域在我的应用程序中每次都不相同。第二个问题是我在运行时从我的服务器域下载 SSL 证书,所以我如何每次更新原始文件夹中的证书文件,因为我们知道我们无法在运行时在原始文件夹中写入文件。

因此,对于动态流程,我如何使用不同的证书连接到 Android N 中的服务器。

编辑1:如果我不使用此配置文件代码,我的应用程序通信将从服务器停止,所以我无论如何都需要使用此代码。

Edit2:这是我的代码,我在其中连接到我的服务器,它给我响应 200 意味着可以,无需更改 android N 的代码(旧代码)。

  CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");

                    InputStream caInput = new BufferedInputStream(new FileInputStream(certFile));
                       X509Certificate ca =(X509Certificate) cf.generateCertificate(caInput);
                    String keyStoreType = KeyStore.getDefaultType();
                    KeyStore keyStore = KeyStore.getInstance(keyStoreType);
                    keyStore.load(null, null);
                    keyStore.setCertificateEntry("ca", ca);

                    // Create a TrustManager that trusts the CAs in our KeyStore
                    String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
                    TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
                    tmf.init(keyStore);
                    TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return new java.security.cert.X509Certificate[]{};
                        }

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

                        public void checkServerTrusted(X509Certificate[] chain,
                                                       String authType) throws CertificateException {
                        }
                    }};
                    // Create an SSLContext that uses our TrustManager
                    HttpsURLConnection.setDefaultHostnameVerifier(new NullHostNameVerifier());
                    SSLContext sslcontext = SSLContext.getInstance("TLS");
                    sslcontext.init(null, trustAllCerts, new java.security.SecureRandom());

                    // Tell the URLConnection to use a SocketFactory from our SSLContext
                    url = new URL(wsdlUrl);
                    HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
                    urlConnection.setSSLSocketFactory(sslcontext.getSocketFactory());
                    urlConnection.setConnectTimeout(5000);
                    urlConnection.connect();

                    if (urlConnection.getResponseCode() == 200) {  //Successful response.
                        result = true;
                    } else {
                        result = false;
                    }
Run Code Online (Sandbox Code Playgroud)

但在 200 响应中,我正在向该服务器调用我的 SOAP 服务方法,在这种情况下我遇到异常

 com.neurospeech.wsclient.SoapFaultException: Server Error 
 at com.neurospeech.wsclient.SoapWebService.postXML(SoapWebService.java:225)
 at com.neurospeech.wsclient.SoapWebService.getSoapResponse(SoapWebService.java:157)
 at com.vxlsoftware.fudmagent.serviceclasses.AndroidServiceAsync.access$1300(AndroidServiceAsync.java:6)
 at com.vxlsoftware.fudmagent.serviceclasses.AndroidServiceAsync$setAndroidClient     HeartbitRequest.executeRequest(AndroidServiceAsync.java:367)
 at com.neurospeech.wsclient.ServiceRequest.run(ServiceRequest.java:20)
 at java.lang.Thread.run(Thread.java:761)
Run Code Online (Sandbox Code Playgroud)

意味着我的连接 url 代码在 Android N 中也工作正常,但 SOAP 服务给了我例外。

我认为我没有很好地定义我的问题,但请任何尝试的人给我任何线索。

Ale*_*bin 5

网络安全配置不支持动态定义的信任锚。因此,您需要使用常规方法创建信任自定义信任锚的自定义 X509TrustManager,从中初始化 SSLContext,从中获取 SSLSocketFactory 或 SSLEngine,并将其传递到 HTTPS 堆栈中。您必须小心地信任此类自定义信任锚,仅用于与特定主机的连接。否则,拥有与自定义信任锚对应的私钥的实体可以对来自您的应用程序的所有网络流量进行中间人攻击。

有关示例,请参阅https://developer.android.com/training/articles/security-ssl.html#UnknownCa。我建议您修改示例代码以禁用 HttpsURLConnection 上的重定向。