【问题标题】:Android N Network Security Configuration for run time downloaded Self-Signed Certificate运行时下载自签名证书的 Android N 网络安全配置
【发布时间】:2017-01-07 21:08:53
【问题描述】:

在用于 SSL 证书的 Android N 中,我必须添加此代码-(根据给定的android developer link

 <?xml version="1.0" encoding="utf-8"?>
 <manifest ... >
<application android:networkSecurityConfig="@xml/network_security_config"
                ... >
    ...
</application>

还有一个 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>

这适用于一个静态域,但我的问题是 - 服务器域在我的应用程序中每次都不会相同。第二个问题是我在运行时从我的服务器域下载 SSL 证书,所以我如何每次都更新原始文件夹中的证书文件,因为我们知道我们不能在运行时在原始文件夹中写入文件。

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

Edit1:如果我不使用此配置文件代码,我的应用程序通信从服务器停止,所以我仍然需要使用此代码。

编辑2: 这是我连接到我的服务器的代码,它给我响应 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;
                    }

但是在 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)

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

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

【问题讨论】:

  • 与其他 Android 版本相同。新的 Android 7 网络安全配置不适用于您的情况。
  • @Robert - 不,我必须使用它,否则我无法与我的服务器通信。实际上我无法解释我实际上在做什么,但为了您的理解,我必须使用这个代码Android N 否则我的应用程序将完全停止运行。
  • 您找到解决此问题的方法了吗?我面临同样的问题,除了通过包含这些密钥库的代理之外似乎没有其他方法。
  • @IgorGanapolsky 对于像我这样的android,我在上面的代码中调用服务来测试我的连接,它工作正常,但如果你也在使用SOAP 服务,那么我现在没有任何解决方案。因此,如果您不使用任何肥皂服务,那么您可以使用我上面的代码进行连接。
  • 所以你的问题更多是关于 SOAP 通信问题,而不是 Android N 网络安全。你的 SOAP 代码在 Marshmallow 上有效吗?

标签: android security https ssl-certificate android-7.0-nougat


【解决方案1】:

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

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

【讨论】:

  • 我仍然需要一个密钥库文件才能使其工作。如果我连接到许多动态服务器,但无法获取这些密钥库文件怎么办?
  • 您可以将 X.509 证书添加到您使用的 X509TrustManager 所基于的 KeyStore。您还可以实现自己的 X509TrustManager,它不依赖于 KeyStore。
  • 你确定它可以在 Android N 上运行吗?我的测试证实并非如此。 Android N 要求设备上存在物理密钥库以获取自签名证书!
  • 我不确定您所说的“设备上存在物理密钥库”是什么意思。您可以从内存中的KeyStore(例如developer.android.com/training/articles/…)创建X509TrustManager,或者您可以实现自己的X509TrustManager,甚至不使用KeyStore。然后,您可以使用X509TrustManager 来初始化SSLContext,这将为您提供SSLSocketFactorySSLEngine
  • 为什么不直接添加您需要的密码套件。喜欢:List&lt;String&gt; cipherSuitesToEnable = new ArrayList&lt;&gt;(); cipherSuitesToEnable.add("SSL_RSA_WITH_RC4_128_SHA"); cipherSuitesToEnable.add("SSL_RSA_WITH_3DES_EDE_CBC_SHA"); sslsock.setEnabledCipherSuites(cipherSuitesToEnable.toArray(new String[cipherSuitesToEnable.size()])); 这应该可以解决需要与 Android N 不同的密码套件的传统 Windows 服务器的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-29
  • 1970-01-01
  • 2011-05-12
  • 2017-12-18
  • 2016-10-07
  • 2019-09-23
相关资源
最近更新 更多