在 android Nougat 中使用自签名证书通过 https 连接时发生 SSL 握手异常

SSL handshake exception while connecting over https using self signed certificate in android Nougat

在我的 android 应用程序中,我通过 https 连接。我正在使用自签名证书进行连接。 它在 api 级别 24 以下的设备上工作(在 android nougat 之前)。但是在 android Nougat 上它抛出 SSL 握手异常:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

这是我通过 https 连接的方式:-

SSLContext context = null;
    try 
    {
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        // Get the raw resource, which contains the keystore with
        // your trusted certificates (root and any intermediate certs)
        InputStream input = new BufferedInputStream(context.getAssets().open(pkcsFilename));
        try {
            // Initialize the keystore with the provided trusted certificates
            // Also provide the password of the keystore
            keyStore.load(input, password.toCharArray());
        } finally {
            input.close();
        }

        KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyFactory.init(keyStore, "".toCharArray());

        // Load CAs from an InputStream
        // (could be from a resource or ByteArrayInputStream or ...)
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        Certificate ca = null;
        input = new BufferedInputStream(context.getAssets().open(certificateFilename));
        try 
        {
            ca = cf.generateCertificate(input);
        }
        finally
        {
            input.close();
        }
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        trustStore.load(null, null);
        trustStore.setCertificateEntry("server", ca);

        // Create a TrustManager that trusts the CAs in our KeyStore
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustStore);

        // Create an SSLContext that uses our TrustManager
        context = SSLContext.getInstance("TLS");
        context.init(keyFactory.getKeyManagers(), tmf.getTrustManagers(), null);

        HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();

我尝试了以下方法link,但没有用。

这是我的网络配置文件。我已将其添加到我的 AndroidManifest.xml 文件中。

    <?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config>
        <domain includeSubdomains="true">xyz.com</domain>
        <trust-anchors>
        <certificates src="@raw/root_ca" />
        </trust-anchors>
    </domain-config>
</network-security-config>

请帮我解决这个问题。

System.setProperty("javax.net.ssl.trustStore",newKeystoreFile.getAbsolutePath());

同样,尝试设置 keystorepassword 和 keypassword 属性 每当您尝试使用以上 属性 时,每次都重新启动服务器 https://docs.oracle.com/cd/E17802_01/webservices/webservices/reference/tutorials/wsit/doc/WSIT_Security6.html

我通过添加自定义信任管理器让它工作。初始化 SSL 上下文时 context.init(keyFactory.getKeyManagers(), tmf.getTrustManagers(), null);

I modified it as :

context.init(keyFactory.getKeyManagers(), new TrustManager[] { tm }, null);
TrustManager tm = new X509TrustManager() {
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                }

                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    for (int j=0; j<chain.length; j++)
                    {
                        chain[j].checkValidity();
                        try {
                            chain[j].verify(ca.getPublicKey());
                        } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchProviderException |
                                SignatureException e) {
                            e.printStackTrace();
                            throw new CertificateException(e.getMessage());
                        }
                    }
                }

                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            };

我用服务器证书验证证书。现在可以使用了。