programing

Android SSL 연결에 대한 트러스트 앵커를 찾을 수 없습니다.

bestprogram 2023. 7. 31. 21:31

Android SSL 연결에 대한 트러스트 앵커를 찾을 수 없습니다.

godaddy 256bit SSL 인증서를 실행하는 IIS6 상자에 연결하려고 하는데 다음 오류가 발생합니다.

java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

무엇이 그것을 야기시킬 수 있는지 알아내려고 노력했지만, 지금은 빈칸을 그리고 있습니다.

연결 방법은 다음과 같습니다.

HttpsURLConnection conn;              
conn = (HttpsURLConnection) (new URL(mURL)).openConnection();
conn.setConnectTimeout(20000);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.connect();
String tempString = toString(conn.getInputStream());

승인된 답변과 달리 사용자 정의 신뢰 관리자가 필요하지 않습니다. 서버 구성을 수정해야 합니다!

잘못 설치된 dynadot/alphassl 인증서로 Apache 서버에 연결하는 동안 동일한 문제가 발생했습니다.HttpsUrlConnection(Java/Android)을 사용하여 연결하고 있습니다.

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

실제 문제는 서버 구성이 잘못되었다는 것입니다. http://www.digicert.com/help/ 등으로 테스트하면 해결책을 알 수 있습니다.

"인증서가 신뢰할 수 있는 기관에 의해 서명되지 않았습니다(Mozilla의 루트 저장소 확인).신뢰할 수 있는 기관에서 인증서를 구입한 경우 하나 이상의 중간 인증서설치하면 됩니다.서버 플랫폼에 대해 이 작업을 수행하는 데 도움이 필요하면 인증서 공급자에게 문의하십시오."

openssl을 사용하여 인증서를 확인할 수도 있습니다.

openssl s_client -debug -connect www.thedomaintocheck.com:443

다음과 같은 정보를 확인할 수 있습니다.

Verify return code: 21 (unable to verify the first certificate)

및 출력의 앞부분에 표시됩니다.

depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=27:certificate not trusted
verify return:1
depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=21:unable to verify the first certificate`

인증서 체인에는 하나의 요소(인증서)만 포함됩니다.

Certificate chain
 0 s:/OU=Domain Control Validated/CN=www.thedomaintocheck.com
  i:/O=AlphaSSL/CN=AlphaSSL CA - G2

그러나 Android가 신뢰하는 기관(Verisign, GlobalSign 등)을 체인으로 다시 참조해야 합니다.

Certificate chain
 0 s:/OU=Domain Control Validated/CN=www.thedomaintocheck.com
   i:/O=AlphaSSL/CN=AlphaSSL CA - G2
 1 s:/O=AlphaSSL/CN=AlphaSSL CA - G2
   i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
 2 s:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
   i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA

서버를 구성하기 위한 지침(및 중간 인증서)은 일반적으로 인증서를 발급한 기관에서 제공합니다(예: http://www.alphassl.com/support/install-root-certificate.html ).

인증서 발급자가 제공한 중간 인증서를 설치한 후 HttpsUrlConnection을 사용하여 연결할 때 오류가 발생하지 않습니다.

@Chrispix의 해결책은 위험합니다!모든 인증서를 신뢰하면 누구나 중간 공격에서 남자를 할 수 있습니다!고객에게 인증서를 보내기만 하면 해당 인증서를 수락할 것입니다.

다음 게시물에 설명된 대로 인증서를 사용자 정의 신뢰 관리자에 추가합니다.HTTPS를 통한 HttpClient를 사용하여 모든 인증서 신뢰

사용자 지정 인증서로 보안 연결을 설정하는 것이 조금 더 복잡하지만 중간 공격에서 사람의 위험 없이 원하는 SSL 암호화 보안을 제공합니다!

런타임에 특정 인증서를 신뢰할 수 있습니다.
서버에서 다운로드하여 자산을 넣고 ssl-utils-android를 사용하여 다음과 같이 로드하면 됩니다.

OkHttpClient client = new OkHttpClient();
SSLContext sslContext = SslUtils.getSslContextForCertificateFile(context, "BPClass2RootCA-sha2.cer");
client.setSslSocketFactory(sslContext.getSocketFactory());

에서 저는 위의예사습니다용했서에다니습사를 했습니다.OkHttpClient그렇지만SSLContextJava의 모든 클라이언트에서 사용할 수 있습니다.

질문이 있으시면 언제든지 물어보세요.저는 이 작은 도서관의 저자입니다.

최신 Android 문서를 기반으로 한 업데이트(2017년 3월):

다음 유형의 오류가 발생할 경우:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
        at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:374)
        at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209)
        at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478)
        at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:433)
        at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
        at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
        at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282)
        at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)
        at libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:271)

이 문제는 다음 중 하나일 수 있습니다.

  1. 서버 인증서를 발급한 CA를 알 수 없습니다.
  2. 서버 인증서가 CA에 의해 서명되지 않았지만 자체 서명되었습니다.
  3. 서버 구성에 중간 CA가 없습니다.

은 해책은가것입다니는치르를 가르치는 것입니다.HttpsURLConnection특정 CA를 신뢰할 수 있습니다. 어떻게요?https://developer.android.com/training/articles/security-ssl.html#CommonProblems 을 확인하십시오.

▁▁are▁who를 사용하는 다른 .AsyncHTTPClientcom.loopj.android:android-async-http라이브러리, HTTPS를 사용하려면 AsyncHttpClient 설치를 선택하십시오.

매우 오래된 게시물에 회신합니다.하지만 아마도 그것은 초보자들에게 도움이 될 것이고 위의 것들 중 어느 것도 잘 되지 않는다면 말입니다.

설명:아무도 설명이 엉터리가 아니라 해결책을 원하지 않는다는 것을 알고 있습니다.그러나 하나의 라이너에서는 로컬 컴퓨터에서 신뢰할 수 없는 원격 컴퓨터로 서비스에 액세스하려고 합니다.원격 서버에서 신뢰를 얻도록 요청해야 합니다.

솔루션:다음 솔루션은 다음 조건이 충족된다고 가정합니다.

  1. 로컬 컴퓨터에서 원격 api에 액세스하려고 합니다.
  2. Android 앱을 구축하고 있습니다.
  3. 원격 서버가 프록시 필터링 중입니다(브라우저 설정에서 프록시를 사용하여 원격 api 서비스(일반적으로 스테이징 또는 개발 서버)에 액세스할 수 있습니다).
  4. 실제 장치에서 테스트 중입니다.

단계:

앱을 등록하려면 .keystore 확장 파일이 필요합니다..keystore 파일을 만드는 방법을 모르는 경우 다음 섹션을 따라 .keystore 파일 만들기 또는 다음 섹션 서명 Apk 파일로 건너뜁니다.

.keystore 파일 생성

Android Studio를 엽니다.상단 메뉴 빌드 > 서명된 APK 생성을 클릭합니다.다음 창에서 Create new...를 클릭합니다.단추를 채우다새 창에서 모든 필드에 데이터를 입력하십시오.두 개의 암호 필드에는 동일한 암호를 사용해야 하며, 다른 암호를 사용하지 마십시오. 또한 맨 위에 있는 저장 경로 키 저장소 경로도 기억하십시오.모든 필드를 입력한 후 확인 버튼을 클릭합니다.

Apk 파일 서명

이제 방금 만든 .keystore 파일로 서명된 앱을 만들어야 합니다.다음 단계를 수행합니다.

  1. 빌드 > Clean Project, 클리닝이 완료될 때까지 기다립니다.
  2. 빌드 > 서명된 APK 생성
  3. Choose existing...단추를 채우다
  4. Create .keystore file 섹션에서 방금 만든 .keystore 파일을 선택합니다.
  5. Create .keystore file 섹션에서 생성한 것과 동일한 암호를 입력합니다.다음에 대해 동일한 암호 사용Key store password그리고.Key password 을 입력합니다.
  6. 다음 단추 클릭
  7. 에서, 사용자 수 .build.gradle.Build Types그리고.Flavors.
  8. Build Types선택하세요.release
  9. 위해서Flavors그러나 그것은 당신의 설정에 달려 있습니다.build.gradle 일파를 선택하세요. 택선staging이방에서면사다니습용했에서 다음 했습니다.build.gradle내 것과 동일하게 사용할 수 있지만, 반드시 변경해야 합니다.applicationId 이름으로

    productFlavors {
        staging {
            applicationId "com.yourapplication.package"
            manifestPlaceholders = [icon: "@drawable/ic_launcher"]
            buildConfigField "boolean", "CATALYST_DEBUG", "true"
            buildConfigField "boolean", "ALLOW_INVALID_CERTIFICATE", "true"
        }
        production {
            buildConfigField "boolean", "CATALYST_DEBUG", "false"
            buildConfigField "boolean", "ALLOW_INVALID_CERTIFICATE", "false"
        }
    }
    
  10. 아래 두 를 클릭합니다.Signature Versions하고 확란및클을 클릭합니다.Finish단추를 채우다

거의 다 왔습니다:

모든 힘든 일이 끝났습니다. 이제 진실의 움직임입니다.프록시로 백업된 스테이징 서버에 액세스하려면 실제 테스트 중인 Android 장치에서 몇 가지 설정을 해야 합니다.

Android 장치의 프록시 설정:

  1. Android 전화기 내부의 설정을 클릭한 다음 Wi-Fi
  2. ㅠㅠㅠ wifi ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠModify network
  3. 다음을 클릭합니다.Advanced options만약 당신이 그것을 볼 수 없다면.Proxy Hostname 취재
  4. Proxy Hostname연결할 호스트 IP 또는 이름을 입력합니다.은 일적인준서이다같습다니음과름은버의비반▁astg.api.mygoodcompany.com
  5. 합니다. 예를 들어 " " " " " " " " " " " 를 입력합니다.9502
  6. 를 .Save단추를 채우다

마지막 한 번:

Sign APK File 섹션에서 서명된 apk 파일을 생성한 것을 기억하십시오.지금은 그 APK 파일을 설치할 시간입니다.

  1. 터미널을 열고 서명된 apk 파일 폴더로 변경
  2. Android 장치를 컴퓨터에 연결합니다.
  3. Android 장치에서 이전에 설치된 모든 pk 파일 제거
  4. 려달을 합니다.adb install name of the apk file
  5. 가 어떤이서위명다령음같반다니환됩이과로 반환됩니다.adb command not found전체 경로를 다음과 같이 입력합니다.C:\Users\shah\AppData\Local\Android\sdk\platform-tools\adb.exe install name of the apk file

저는 그 문제가 해결되기를 바랍니다.그렇지 않다면 저에게 댓글을 남겨주세요.

살람!

https://www.ssllabs.com/ssltest/ 을 사용하여 도메인을 테스트합니다.

코틀린의 시하브 우딘의 해결책.

import java.security.SecureRandom
import java.security.cert.X509Certificate
import javax.net.ssl.*
import javax.security.cert.CertificateException

object {

    val okHttpClient: OkHttpClient
    val gson: Gson
    val retrofit: Retrofit

    init {

        okHttpClient = getOkHttpBuilder()
            // Other parameters like connectTimeout(15, TimeUnit.SECONDS)
            .build()

        gson = GsonBuilder().setLenient().create()

        retrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build()
    }

    fun getOkHttpBuilder(): OkHttpClient.Builder =
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            OkHttpClient().newBuilder()
        } else {
            // Workaround for the error "Caused by: com.android.org.bouncycastle.jce.exception.ExtCertPathValidatorException: Could not validate certificate: Certificate expired at".
            getUnsafeOkHttpClient()
        }

    private fun getUnsafeOkHttpClient(): OkHttpClient.Builder =
        try {
            // Create a trust manager that does not validate certificate chains
            val trustAllCerts: Array<TrustManager> = arrayOf(
                object : X509TrustManager {
                    @Throws(CertificateException::class)
                    override fun checkClientTrusted(chain: Array<X509Certificate?>?,
                                                    authType: String?) = Unit

                    @Throws(CertificateException::class)
                    override fun checkServerTrusted(chain: Array<X509Certificate?>?,
                                                    authType: String?) = Unit

                    override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
                }
            )
            // Install the all-trusting trust manager
            val sslContext: SSLContext = SSLContext.getInstance("SSL")
            sslContext.init(null, trustAllCerts, SecureRandom())
            // Create an ssl socket factory with our all-trusting manager
            val sslSocketFactory: SSLSocketFactory = sslContext.socketFactory
            val builder = OkHttpClient.Builder()
            builder.sslSocketFactory(sslSocketFactory,
                trustAllCerts[0] as X509TrustManager)
            builder.hostnameVerifier { _, _ -> true }
            builder
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
}

를 사용하는 경우에도 동일한 오류가 표시됩니다.Glide이미지가 표시되지 않습니다.이 문제를 해결하려면 Glide - javax.net .ssl을 참조하십시오.SSL HandshakeException: java.security.cert.CertPathValidator예외: 인증 경로에 대한 트러스트 앵커를 찾을 수 없으며 OkHttpClient를 글라이드에 설정하는 방법입니다.

@GlideModule
class MyAppGlideModule : AppGlideModule() {

    val okHttpClient = Api.getOkHttpBuilder().build() // Api is the class written above.
    // It is better to create okHttpClient here and not use Api.okHttpClient,
    // because their settings may differ. For instance, it can use its own
    // `addInterceptor` and `addNetworkInterceptor` that can affect on a read JSON.


    override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
        registry.replace(GlideUrl::class.java, InputStream::class.java,
            OkHttpUrlLoader.Factory(okHttpClient))
    }
}

build.gradle:

// Glide.
implementation 'com.github.bumptech.glide:glide:4.11.0'
implementation 'com.github.bumptech.glide:okhttp3-integration:4.11.0'
kapt 'com.github.bumptech.glide:compiler:4.11.0'

갱신하다

API 16 에뮬레이터에서 또 다른 오류가 발생했습니다.

루틴:SSL23_GET_SERVER_HELLO:tlsv1 경고 프로토콜 버전(external/openssl/ssl/s23_clnt.c:741').

1과 2를 읽고 코드를 바꿨습니다.

okHttpClient = getOkHttpBuilder().build()

private fun getOkHttpBuilder(): OkHttpClient.Builder {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        Security.insertProviderAt(Conscrypt.newProvider(), 1)
    }
    return OkHttpClient().newBuilder()
}

// build.gradle:
implementation 'org.conscrypt:conscrypt-android:2.5.1'

는 또한 한또이라제니다습거했을들인에서 이 했습니다.MyApplication:

try {
    ProviderInstaller.installIfNeeded(applicationContext)
    val sslContext = SSLContext.getInstance("TLSv1.2")
    sslContext.init(null, null, null)
    sslContext.createSSLEngine()
} catch (e: GooglePlayServicesRepairableException) {
    Timber.e(e.stackTraceToString())
    // Prompt the user to install/update/enable Google Play services.
    GoogleApiAvailability.getInstance().showErrorNotification(this, e.connectionStatusCode)
} catch (e: GooglePlayServicesNotAvailableException) {
    Timber.e(e.stackTraceToString())
    // Prompt the user to install/update/enable Google Play services.
    // GoogleApiAvailability.getInstance().showErrorNotification(this, e.errorCode)
} catch (e: NoSuchAlgorithmException) {
    Timber.e(e.stackTraceToString())
} catch (e: KeyManagementException) {
    Timber.e(e.stackTraceToString())
}

그러나 라이브러리는 pk에 3.4Mb를 추가합니다.

제가 발견한 것과 같은 문제가 있었는데, 제가 제공한 인증서 .crt 파일에 중간 인증서가 누락되었습니다.그래서 서버 관리자에게 모든 .crt 파일을 요청한 후 역순으로 연결했습니다.

예 1. Root.crt 2.Inter.crt 3. myCrt.crt

Windows에서 복사 Inter.crt + Root.crt newCertificate.crt를 실행했습니다.

(여기서 나는 내 Crt.crt를 무시했습니다.

그런 다음 새로운 Certificate.crt 파일을 입력 스트림을 통해 코드로 제공했습니다.작업 완료.

제가 받는 오류 메시지는 비슷했지만, 그 이유는 자체 서명된 인증서가 만료되었기 때문입니다.openssl 클라이언트를 시도했을 때 파이어폭스에서 인증서 대화상자를 확인할 때 간과되었던 이유를 알려주었습니다.

따라서 일반적으로 인증서가 키 저장소에 있고 해당 인증서의 "VALID"가 있으면 이 오류가 발생합니다.

안드로이드 클라이언트에서 쿠렌토 서버로 연결할 때도 같은 문제가 있었습니다.쿠렌토 서버는 jks 인증서를 사용하기 때문에 pem을 변환해야 했습니다.변환 입력으로 cert.pem 파일을 사용했는데 이러한 오류가 발생했습니다.하지만 체인을 사용한다면요.cert.pem 대신 pem - 모두 정상입니다.

모든 인증서를 신뢰할 필요는 없지만 자체 서명된 인증서가 있는 디버깅 환경에서 문제가 발생하여 더티 솔루션이 필요했습니다.

내가 해야 할 일은 컴퓨터의 초기화를 변경하는 것이었습니다.sslContext

mySSLContext.init(null, trustAllCerts, null); 

trustAllCerts다음과 같이 생성되었습니다.

private final 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 {
    }
} };

이것이 도움이 되기를 바랍니다.

제 경우 루트 및 중간 인증서가 설치되었지만 "인증 경로에 대한 트러스트 앵커를 찾을 수 없습니다." 예외가 발생했습니다.안드로이드 문서를 발굴한 결과 기본적으로 모든 앱의 보안 연결(TLS, HTTPS 등 프로토콜 사용)이 사전 설치된 시스템 CA를 신뢰하고, 안드로이드 6.0(API 레벨 23) 이하를 대상으로 하는 앱도 기본적으로 사용자가 추가한 CA 스토어를 신뢰하는 것으로 나타났습니다.api 레벨이 23보다 높은 OS에서 실행 중인 앱은 아래와 같이 network_security_config에 주소를 추가하여 사용자가 추가한 CA를 앱이 신뢰하도록 명시적으로 허용해야 합니다.

<domain-config>
        <domain includeSubdomains="true">PUT_YOUR_SERVER_ADDERESS</domain>
        <trust-anchors>
            <certificates src="user" />
        </trust-anchors>
</domain-config>

트러스트 앵커 오류는 여러 가지 이유로 발생할 수 있습니다.나에게 있어서는 단순히 접근하려고 했던 것뿐입니다.https://example.com/https://www.example.com/.

따라서 신뢰 관리자를 직접 작성하기 전에 URL을 다시 확인하는 것이 좋습니다(저와 마찬가지로).

테스트 버전 노출을 위해 자체 서명된 인증서를 사용하는 외부 웹 서비스를 사용하려고 할 때도 같은 문제가 발생했습니다.전 세계적으로 문제를 해결하기 위해 사용한 단계는 다음과 같습니다(Retrofit, oKhttp, HttpUrlConnection 등 어떤 프레임워크를 사용하든 적용됩니다).

  1. 크롬으로 도메인 로드(https://dev.thedomain.private)
  2. 를 . 형식der 형로인내다니보냅를)으로 .padlock symbol 근에서면, 다렇그처를 입력합니다.details그리고나서export합니다.der형식)
  3. 합니다. Folder Der 원 Folder 저합 니장 다에 시를 ▁for니다 ▁saveres/raw/dev_thedomain_private.der
  4. 만들기에서 보안 resources/xml
    <?xml version="1.0" encoding="utf-8"?>
    <network-security-config>
        <domain-config>
            <domain includeSubdomains="true">dev.thedomain.private</domain>
            <trust-anchors>
                <certificates src="@raw/dev_thedomain_private"/>
            </trust-anchors>
        </domain-config>
    </network-security-config>
  1. 응용 프로그램 태그 아래 매니페스트의 보안 구성을 참조합니다.
    <application
        android:networkSecurityConfig="@xml/network_security_config"

끝났습니다!이제 인증서를 신뢰할 수 있습니다...

진저브레드 전화기에서는 항상 다음과 같은 오류가 발생합니다.Trust Anchor not found for Android SSL Connection내 자격증에 의존하도록 설정하더라도.

사용하는 코드는 다음과 같습니다(스칼라 언어).

object Security {
    private def createCtxSsl(ctx: Context) = {
        val cer = {
            val is = ctx.getAssets.open("mycertificate.crt")
            try
                CertificateFactory.getInstance("X.509").generateCertificate(is)
            finally
                is.close()
        }
        val key = KeyStore.getInstance(KeyStore.getDefaultType)
        key.load(null, null)
        key.setCertificateEntry("ca", cer)

        val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm)
    tmf.init(key)

        val c = SSLContext.getInstance("TLS")
        c.init(null, tmf.getTrustManagers, null)
        c
    }

    def prepare(url: HttpURLConnection)(implicit ctx: Context) {
        url match {
            case https: HttpsURLConnection ⇒
                val cSsl = ctxSsl match {
                    case None ⇒
                        val res = createCtxSsl(ctx)
                        ctxSsl = Some(res)
                        res
                    case Some(c) ⇒ c
                }
                https.setSSLSocketFactory(cSsl.getSocketFactory)
            case _ ⇒
        }
    }

    def noSecurity(url: HttpURLConnection) {
        url match {
            case https: HttpsURLConnection ⇒
                https.setHostnameVerifier(new HostnameVerifier {
                    override def verify(hostname: String, session: SSLSession) = true
                })
            case _ ⇒
        }
    }
}

연결 코드는 다음과 같습니다.

def connect(securize: HttpURLConnection ⇒ Unit) {
    val conn = url.openConnection().asInstanceOf[HttpURLConnection]
    securize(conn)
    conn.connect();
    ....
}

try {
    connect(Security.prepare)
} catch {
    case ex: SSLHandshakeException /*if ex.getMessage != null && ex.getMessage.contains("Trust anchor for certification path not found")*/ ⇒
        connect(Security.noSecurity)
}

기본적으로 사용자 지정 인증서를 신뢰하도록 설정합니다.실패하면 보안을 해제합니다.이것이 최선의 선택은 아니지만 오래된 전화기와 버그가 있는 전화기를 사용할 수 있는 유일한 선택입니다.

이 샘플 코드는 자바로 쉽게 번역할 수 있습니다.

이것이 매우 오래된 기사라는 것을 알지만, 저는 제 트러스트 앵커 문제를 해결하려고 할 때 이 기사를 접했습니다.저는 제가 어떻게 그것을 고쳤는지 게시했습니다.루트 CA를 미리 설치한 경우 매니페스트에 구성을 추가해야 합니다.

https://stackoverflow.com/a/60102517/114265

저의 경우 안드로이드 8.0으로 업데이트한 후에 이러한 현상이 발생했습니다.Android가 신뢰하도록 설정된 자체 서명 인증서는 SHA1과 RSA를 함께 사용하는 서명 알고리즘을 사용했습니다.서명 알고리즘 SHA256을 RSA와 함께 사용하여 새 인증서로 전환하여 문제를 해결했습니다.

저는 비슷한 문제를 겪었고 모든 출처를 신뢰하는 전략을 완전히 배제했습니다.

Kotlin에서 구현된 애플리케이션에 적용된 솔루션을 여기에 공유합니다.

먼저 다음 웹 사이트를 사용하여 인증서와 인증서의 유효성에 대한 정보를 얻을 것을 권장합니다.

Android 기본 트러스트 스토어에 'Accepted Issuers'로 표시되지 않으면 해당 인증서를 가져와 응용 프로그램에 통합하여 사용자 지정 트러스트 스토어를 만들어야 합니다.

제 경우 이상적인 솔루션은 사용자 지정 및 Android 기본 신뢰 저장소를 결합한 상위 수준의 신뢰 관리자를 만드는 것이었습니다.

여기서 그는 Retrofit과 함께 사용한 OkHttpClient를 구성하는 데 사용되는 고급 코드를 표시합니다.

override fun onBuildHttpClient(httpClientBuild: OkHttpClient.Builder) {

        val trustManagerWrapper = createX509TrustManagerWrapper(
            arrayOf(
                getCustomX509TrustManager(),
                getDefaultX509TrustManager()
            )
        )

        printX509TrustManagerAcceptedIssuers(trustManagerWrapper)

        val sslSocketFactory = createSocketFactory(trustManagerWrapper)
        httpClientBuild.sslSocketFactory(sslSocketFactory, trustManagerWrapper)

    }

이러한 방식으로 자체 서명된 인증서를 사용하여 서버와 통신하고 신뢰할 수 있는 인증 기관에서 발급한 인증서를 사용하여 다른 서버와 통신할 수 있습니다.

바로 이거예요, 누군가에게 도움이 됐으면 좋겠어요.

때때로 관리자가 인증서를 잘못 설정할 때 발생합니다. 여기에서 URL을 확인하십시오.

저의 경우, 오류가 있었습니다.

일부 웹 브라우저에서는 인증서를 신뢰할 수 없습니다.신뢰할 수 있는 루트 인증서에 연결하려면 중간/체인 인증서를 설치해야 할 수 있습니다.이 오류에 대해 자세히 알아봅니다.서버 플랫폼에 대한 GlobalSign의 인증서 설치 지침에 따라 이 문제를 해결할 수 있습니다.중간 인증서에 대한 부분에 주목합니다.

제 경우 웹사이트의 인증서는 정확했지만(Issuer = GlobalSign RSA OV SSL CA 2018) 다운로드 중인 인증서 파일은 잘못된 것이었습니다. 인증서를 "다운로드"하고 브라우저 앞에서 다운로드할 새 인증서를 전달하는 안티바이러스 때문입니다(Issuer = ESET SSL Filter CA)!!

인증서 파일의 발급자가 올바른지 확인합니다.

저는 위의 솔루션 중 하나가 저를 위해 작동하는 이러한 방법을 사용합니다: 첫 번째:

   public  okhttp3.OkHttpClient getUnsafeOkHttpClient() {
    try {
        // Create a trust manager that does not validate 
   certificate chains
        final TrustManager[] trustAllCerts = new TrustManager[] {
                new X509TrustManager() {
                    @Override
                    public void 
   checkClientTrusted(java.security.cert.X509Certificate[] chain, 
   String authType) throws CertificateException {
                    }

                    @Override
                    public void 
  checkServerTrusted(java.security.cert.X509Certificate[] chain, 
  String authType) throws CertificateException {
                    }

                    @Override
                    public java.security.cert.X509Certificate[] 
   getAcceptedIssuers() {
                        return new 
  java.security.cert.X509Certificate[]{};
                    }
                }
        };

        // Install the all-trusting trust manager
        final SSLContext sslContext = 
  SSLContext.getInstance("SSL");
        sslContext.init(null, trustAllCerts, new 
  java.security.SecureRandom());

        // Create an ssl socket factory with our all-trusting 
       manager
        final SSLSocketFactory sslSocketFactory = 
       sslContext.getSocketFactory();

        okhttp3.OkHttpClient.Builder builder = new 
      okhttp3.OkHttpClient.Builder();
        builder.sslSocketFactory(sslSocketFactory, 
      (X509TrustManager)trustAllCerts[0]);
        builder.hostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession 
       session) {
                return true;
            }
        });

        okhttp3.OkHttpClient okHttpClient = builder.build();
        return okHttpClient;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

두 번째:

    @SuppressLint("TrulyRandom")
    public static void handleSSLHandshake() {
    try {
        TrustManager[] trustAllCerts = new TrustManager[]{new 
       X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }

            @Override
            public void checkClientTrusted(X509Certificate[] 
        certs, String authType) {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] 
       certs, String authType) {
            }
        }};

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new SecureRandom());
        



  HttpsURLConnection
 .setDefaultSSLSocketFactory(sc.getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier(new 
    HostnameVerifier() {
            @Override
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }
        });
    } catch (Exception ignored) {
    }
}

및: 이 라이브러리를 클래스 경로에 배치합니다.

 implementation 'com.squareup.okhttp:okhttp:2.3.0'
implementation 'com.squareup.okhttp:okhttp-urlconnection:2.3.0'
    androidTestImplementation 'androidx.test.espresso:espresso- 
    core:3.3.0'

반에서 그들에게 전화하는 것을 잊지 마세요.

**Set proper alias name**
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509","BC");
            X509Certificate cert = (X509Certificate) certificateFactory.generateCertificate(derInputStream);
            String alias = cert.getSubjectX500Principal().getName();
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            trustStore.load(null);
trustStore.setCertificateEntry(alias, cert);

클라이언트를 다시 연결합니다. 아래와 같이 var httpClient = new HttpClient(새 시스템).넷. http.HttpClientHandler();

https를 http로 변경

언급URL : https://stackoverflow.com/questions/6825226/trust-anchor-not-found-for-android-ssl-connection