ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Kotlin] Retrofit2에서 Trust anchor for certification path not found 에러가 날 때
    개발일지/Kotlin 2024. 4. 24. 18:59

    정확한 원인과 해당 버전이 맞는지 모르겠는데 Android 10버전 이상에서는 발생하지 않았던 것이 Android 6버전인 단말기에서 SSL handshake error 이슈가 발생한다(같은 API 주소를 경유하는데).

    TrustOkHttpClientUtil.kt

    import okhttp3.OkHttpClient
    import java.lang.Exception
    import java.lang.RuntimeException
    import java.security.SecureRandom
    import java.security.cert.CertificateException
    import java.security.cert.X509Certificate
    import javax.net.ssl.SSLContext
    import javax.net.ssl.TrustManager
    import javax.net.ssl.X509TrustManager
    import kotlin.Throws
    
    object TrustOkHttpClientUtil {
        val unsafeOkHttpClient: OkHttpClient
        .Builder
            get() = try {
                val trustAllCerts = arrayOf<TrustManager>(
                    object : X509TrustManager {
                        @Throws(CertificateException::class)
                        override fun checkClientTrusted(
                            chain: Array<X509Certificate>,
                            authType: String
                        ) {
                        }
    
                        @Throws(CertificateException::class)
                        override fun checkServerTrusted(
                            chain: Array<X509Certificate>,
                            authType: String
                        ) {
                        }
    
                        override fun getAcceptedIssuers(): Array<X509Certificate> {
                            return arrayOf()
                        }
                    }
                )
                
                val sslContext = SSLContext.getInstance("SSL")
                sslContext.init(null, trustAllCerts, SecureRandom())
                
                val sslSocketFactory = sslContext.socketFactory
                val builder = OkHttpClient.Builder()
                builder.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
                builder.hostnameVerifier { hostname, session -> true }
                builder
            } catch (e: Exception) {
                throw RuntimeException(e)
            }
    }

    HttpClient2.kt

    import com.myapp.TrustOkHttpClientUtil.unsafeOkHttpClient
    import retrofit2.Retrofit
    import retrofit2.converter.gson.GsonConverterFactory
    
    
    object HttpClient {
        var retrofit: Retrofit? = null
            get() {
                if (field == null) {
                    val builder = Retrofit.Builder()
                    builder.baseUrl("https://myserver.com/api/")
                    builder.addConverterFactory(GsonConverterFactory.create())
                    builder.client(unsafeOkHttpClient.build())
                    field = builder.build()
    
                }
                return field
            }
            private set
    }

    builder.client(unsafeOkHttpClient.build()) // 이 부분 추가

    우회 접속 코드용 클래스를 새로 생성하고 임시 조치 했다.(보안상 권장하지 않는다고 함. 그리고 서버 API의 SSL 인증서가 하필 let's encrypt 인증서라 3개월마다 갱신해야함, 그 때마다 인증서를 교체하고 새로 빌드를 해야 하는 상황이 발생. 다른 방법을 찾아봐야지...)

    댓글

Designed by Tistory.