Android 10ベースのHTTPS証明書検証の無視

17913 ワード

文書ディレクトリ
  • なぜ証明書検証
  • を無視するのか
  • 証明書の検証が不合格です.どうすればいいですか?

  • 証明書検証を無視する理由
    Android 9からアプリのデフォルトアクセスを開始するURLはHTTPSプロトコルでなければならないので、HTTPをサポートするように構成することはできますが、このようなやり方は使用をお勧めしません.0202年になりましたが、HTTPSはすでに主流です.HTTPSプロトコルを使用する以上、CA証明書が欠かせません.この証明書は有料です.1年の有効期限の無料証明書もありますが、個人開発者として、自分でプロジェクトを作って、開発用を作って、全く必要ありません.JDKのkeytoolを使ってhttps証明書を生成します.具体的な方法はネット上にたくさんありますが、ここでは説明しません.
    自作証明書なのでブラウザやシステムでは認められませんが、AndroidでOkHttpを使用してアクセスすると、次のようなエラーが表示されます.
    W/System.err: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
    2020-03-31 12:27:58.570 26059-26059/com.s W/System.err:     at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:231)
    2020-03-31 12:27:58.570 26059-26059/com.s W/System.err:     at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:367)
    2020-03-31 12:27:58.570 26059-26059/com.s W/System.err:     at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:325)
    2020-03-31 12:27:58.571 26059-26059/com.s W/System.err:     at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:197)
    2020-03-31 12:27:58.571 26059-26059/com.s W/System.err:     at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:233)
    2020-03-31 12:27:58.571 26059-26059/com.s W/System.err:     at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:107)
    2020-03-31 12:27:58.571 26059-26059/com.s W/System.err:     at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:75)
    2020-03-31 12:27:58.571 26059-26059/com.s W/System.err:     at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:245)
    2020-03-31 12:27:58.571 26059-26059/com.s W/System.err:     at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
    2020-03-31 12:27:58.571 26059-26059/com.s W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
    2020-03-31 12:27:58.571 26059-26059/com.s W/System.err:     at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:82)
    2020-03-31 12:27:58.571 26059-26059/com.s W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
    2020-03-31 12:27:58.571 26059-26059/com.s W/System.err:     at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
    2020-03-31 12:27:58.571 26059-26059/com.s W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
    2020-03-31 12:27:58.572 26059-26059/com.s W/System.err:     at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:74)
    2020-03-31 12:27:58.572 26059-26059/com.s W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
    

    証明書の検証に失敗しました.どうすればいいですか?
    OkHttpに証明書の検証を無視させる必要があります.ネット上では多くの方法があります.
    /**
         * OkHttpClient   
         */
        private fun newClient(): OkHttpClient = OkHttpClient.Builder().apply {
                connectTimeout(30, TimeUnit.SECONDS)//     :30s  
                readTimeout(10, TimeUnit.SECONDS)//     :10s  
                writeTimeout(10, TimeUnit.SECONDS)//     :10s  
            //        start
            val x509 = MyX509()
            sslSocketFactory(getSSLFactory(x509), x509)
            hostnameVerifier(HostnameVerifier { _, _ -> true })
            //        end
            }.build()
            
    private fun getSSLFactory(x509TrustManager: X509TrustManager): SSLSocketFactory {
            val trustAllCerts = arrayOf<TrustManager>(x509TrustManager)
            val sslContext = SSLContext.getInstance("SSL")
            sslContext.init(null, trustAllCerts, java.security.SecureRandom())
            return sslContext.socketFactory
        }
        
    class MyX509 : X509TrustManager {
    
            override fun getAcceptedIssuers(): Array<X509Certificate> {
                return arrayOf()
            }
    
            @Throws(CertificateException::class)
            override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {
            }
    
            @Throws(CertificateException::class)
            override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {
            }
        }
    

    このように構成するとAndroid 10で次のエラーが表示されます.
    08:20:04 V/InstrumentationResultParser: java.lang.IllegalArgumentException: Required method checkServerTrusted(X509Certificate[], String, String, String) missing
    08:20:04 V/InstrumentationResultParser: at android.net.http.X509TrustManagerExtensions.(X509TrustManagerExtensions.java:71)
    08:20:04 V/InstrumentationResultParser: at okhttp3.internal.platform.android.Android10CertificateChainCleaner.(Android10CertificateChainCleaner.kt:36)
    08:20:04 V/InstrumentationResultParser: at okhttp3.internal.platform.Android10Platform.buildCertificateChainCleaner(Android10Platform.kt:62)
    08:20:04 V/InstrumentationResultParser: at okhttp3.internal.tls.CertificateChainCleaner$Companion.get(CertificateChainCleaner.kt:42)
    08:20:04 V/InstrumentationResultParser: at okhttp3.OkHttpClient$Builder.sslSocketFactory(OkHttpClient.kt:751)
    08:20:04 V/InstrumentationResultParser: at okhttp.android.test.OkHttpTest.testCustomTrustManager(OkHttpTest.kt:437)
    08:20:04 V/InstrumentationResultParser: at java.lang.reflect.Method.invoke(Native Method)
    08:20:04 V/InstrumentationResultParser: at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    08:20:04 V/InstrumentationResultParser: at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    08:20:04 V/InstrumentationResultParser: at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    08:20:04 V/InstrumentationResultParser: at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    08:20:04 V/InstrumentationResultParser: at okhttp3.OkHttpClientTestRule$apply$1.evaluate(OkHttpClientTestRule.kt:111)
    08:20:04 V/InstrumentationResultParser: at okhttp3.testing.PlatformRule$apply$1.evaluate(PlatformRule.kt:66)
    

    実はこの問題はすでにOkHttpのGitHubでissuesを提案している人がいて、具体的な解決策はX 509 TrustManagerの実装クラスをX 509 ExtendedTrustManagerの実装クラスに変えればいいのです.
    @RequiresApi(Build.VERSION_CODES.N)
        class MyX509 : X509ExtendedTrustManager() {
            override fun checkClientTrusted(
                chain: Array<out X509Certificate>?,
                authType: String?,
                socket: Socket?
            ) {
            }
    
            override fun checkClientTrusted(
                chain: Array<out X509Certificate>?,
                authType: String?,
                engine: SSLEngine?
            ) {
            }
    
            override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {
            }
    
            override fun checkServerTrusted(
                chain: Array<out X509Certificate>?,
                authType: String?,
                socket: Socket?
            ) {
            }
    
            override fun checkServerTrusted(
                chain: Array<out X509Certificate>?,
                authType: String?,
                engine: SSLEngine?
            ) {
            }
    
            override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {
            }
    
            override fun getAcceptedIssuers(): Array<X509Certificate> {
                return arrayOf()
            }
        }
    

    関連issuesアドレス