0

我需要在我的应用程序上添加一个自签名证书,为此,我设置了网络安全配置。它在 API 31 上完美运行,但是当我在 API 21 上尝试时,

javax.net.ssl.SSLHandshakeException:java.security.cert.CertPathValidatorException:找不到证书路径的信任锚。

出现错误。

我在Android 文档中看到

面向 Android 6.0(API 级别 23)及更低版本的应用默认也信任用户添加的 CA 商店

所以即使

android:networkSecurityConfig="@xml/network_security_config"

我清单中的行仅用于 API 级别 24 及更高级别,我知道它应该在 API 级别 23 及更低级别中正常工作。(或者也许我错了?)

有关信息,我的 res/xlm 文件夹中的 network_security_config.xml 存储如下:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
    <domain includeSubdomains="true">my.server.ip</domain>
    <trust-anchors>
        <certificates src="@raw/my_pem_cert"/>
    </trust-anchors>
</domain-config>
</network-security-config>

我的 my_pem_cert.pem 存储在 res/raw 文件夹中,如下所示:

-----BEGIN CERTIFICATE-----
ekfozjoiejzfz...
-----END CERTIFICATE-----

您知道为什么它不适用于 API 级别 23 及更低的级别吗?

4

1 回答 1

0

为了帮助那些有同样问题的人,我没有找到为什么它不起作用,所以我做了以下工作以便能够与我的服务器通信:

if ( android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.M) {
    try {
        val caInput: InputStream = resources.openRawResource(R.raw.my_pem_cert)
        // Create a KeyStore containing our trusted CAs
        val keyStore = KeyStore.getInstance(KeyStore.getDefaultType())
        keyStore.load(null, null)
        keyStore.setCertificateEntry("ca", 
            try { 
     CertificateFactory.getInstance("X.509").generateCertificate(caInput)
            } finally {
                caInput.close()
            }
        )
        // Create a TrustManager that trusts the CAs in our KeyStore
        val tmf: TrustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
        tmf.init(keyStore)
        // Create an SSLContext that uses our TrustManager
        val sslContext: SSLContext = SSLContext.getInstance("TLS")
        sslContext.init(null, tmf.getTrustManagers(), null)
        Volley.newRequestQueue(context,HurlStack(null, sslContext.socketFactory)).add(temp)
    } catch (err : Exception) {
        FirebaseCrashlytics.recordException(err)
    }
} else {
    Volley.newRequestQueue(context).add(temp)
}

因此,在 Android M (LVL 23) 及更低版本中,我创建并使用自定义 SSL 套接字工厂来执行我的请求。否则,我使用网络安全配置。

于 2022-02-28T16:11:05.930 回答