Android SSL 연결에 대한 신뢰 앵커를 찾을 수 없습니다


185

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()); 

답변:


78

@Chrispix의 솔루션은 위험합니다! 모든 인증서를 신뢰하면 누구나 중간 공격에서 사람을 할 수 있습니다! 모든 인증서를 고객에게 보내면 수락합니다!

이 게시물에 설명 된대로 인증서를 사용자 정의 신뢰 관리자에 추가하십시오. HTTPS를 통해 HttpClient를 사용하여 모든 인증서 신뢰

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


1
자체 생성 된 인증서로 작업해도 괜찮지 만 루트 CA에 유효한 체인을 가진 OP와 같은 인증서의 경우 잘못 구성된 서버의 해결 방법 일뿐입니다. 내 답변을 참조하십시오.
Stevie

4
@Stevie 모든 인증서 수락은 개념 증명 테스트를위한 옵션 일 뿐이며 SSL 연결은 테스트하려는 부분이 아닙니다. 그렇지 않으면 연결이 안전하지 않기 때문에 모든 인증서를 수락하면 SSL을 사용할 필요가 없습니다!
Matthias B

1
아 죄송합니다. 오해가 있다고 생각합니다. 모든 인증서를 누구도 수락해서는 안된다는 데 완전히 동의합니다! :) 내 의견은 두 번째 단락-사용자 정의 트러스트 관리자 사용 제안-IMHO가 권장 솔루션이 아닌 최후의 해결 방법이어야한다는 의견이었습니다.
Stevie

2
사람들은 그것을 '임시 해결 방법'으로 보지 않았기 때문에 더 많은 문제를 일으키지 않기 위해 해결 방법으로 붙여 넣은 '솔루션'을 제거했습니다.
Chrispix

7
@Chrispix, 당신은 부분적인 수정을 제거하지 말았어야, 단지 테스트 목적을 위해 그것의 좋은
휴고 Allexis 카르 도나

224

허용되는 답변과 달리 사용자 정의 트러스트 관리자가 필요 하지 않으므로 서버 구성을 수정해야합니다!

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

...하지만 체인에서 서명 기관을 참조해야합니다 (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을 사용하여 연결할 때 오류가 없습니다.


3
OP가 연결중인 서버 SSL 구성에 액세스 할 수있는 경우 솔루션 일 수 있습니다. 그러나 그가 서비스를 호스팅하는 사람이 아닌 경우 자신의 측면에서 문제를 해결해야합니다. 이는 사용자 정의 신뢰 관리자를 구현하는 것을 의미합니다.
Matthias B

9
귀하의 솔루션은 의심의 여지없이 작동하지만 근본 원인에 대한 해결책이 아니라 해결책이라는 데 동의하지 않습니까? 3 개의 클라이언트 (Android, iOS, Windows Mobile)에서 서버에 연결해야하는 경우 3 개 모두에 대한 해결 방법을 적용해야합니다. 반면 서버를 한 번 수정하면 모두 "작동합니다".
Stevie

2
Stevie에게 감사합니다. 서버를 3 개월 동안 잘못 구성했으며 지금 만이 문제를 감지했습니다! 이제 내 안드로이드 앱이 100 % 작동합니다
jpros

2
@Stevie 나는 동일한 도메인을 공유하는 다른 API를 여러 번 호출하지만 그중 하나만 (javax.net.ssl.SSLHandshakeException) 실패합니다 ... 왜 그런 일이 일어날 지 알 수 있습니까? 그리고 SSL 인증서는 신뢰할 수 없습니다. 따라서 모든 호출이 동일한 예외로 실패해야한다고 생각했습니다.
공정한 선수

1
@dvaey GET 서버를 소유하고 자신의 설정이 파괴되고 자신이 제대로 작동하지 않을 HTTPS 그들에게 말해 않는 누구와 연락을 - 그들에게 그것을 증명하기 위해이 링크를 제공 digicert.com/help을 ... 나는 그들이 빠른에 감사하고있을 것입니다 상상 결의. 그렇지 않으면 다른 답변의 해결 단계 중 하나를 수행해야하지만 인증서가 만료되고 사용자 지정 신뢰 저장소가 더 이상 새로운 신뢰와 일치하지 않으면 보안을 허용하지 않거나 (인증서 무시) 앱을 다시 배포해야합니다 증명서.
Stevie

17

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

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

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

질문이 있으시면 언제든지 문의하십시오. 저는이 작은 도서관의 저자입니다.


.pfx는 어떻습니까?
Choletski

2
APK가 있으면 앱의 자산 폴더에 액세스 할 수 있기 때문에 안전하지 않습니까?
파트리스 안 달라

1
@PatriceAndala, 루트 CA는 공개적으로 사용할 수 있으므로 괜찮습니다
BekaBot

17

최신 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를 확인 하십시오

사용하는 기타 AsyncHTTPClient에서 com.loopj.android:android-async-http라이브러리를 확인하시기 바랍니다 HTTPS를 사용하도록 설정 AsyncHttpClient을 .


5
okhttp 클라이언트를 사용하는 경우는 어떻습니까?
TheLearner

okhttp의 경우 pls는 @mklimek의 답변을 확인하십시오.
user1506104

14

개조를 사용하는 경우 OkHttpClient를 사용자 정의해야합니다.

retrofit = new Retrofit.Builder()
                        .baseUrl(ApplicationData.FINAL_URL)
                        .client(getUnsafeOkHttpClient().build())
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();

전체 코드는 다음과 같습니다.

    public class RestAdapter {

    private static Retrofit retrofit = null;
    private static ApiInterface apiInterface;

    public static OkHttpClient.Builder 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();

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

    public static ApiInterface getApiClient() {
        if (apiInterface == null) {

            try {
                retrofit = new Retrofit.Builder()
                        .baseUrl(ApplicationData.FINAL_URL)
                        .client(getUnsafeOkHttpClient().build())
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();

            } catch (Exception e) {

                e.printStackTrace();
            }


            apiInterface = retrofit.create(ApiInterface.class);
        }
        return apiInterface;
    }

}

1
코드를 사용하려고하는데 다음 오류가 다시 발생합니다. "javax.net.ssl.SSLHandshakeException : java.security.cert.CertPathValidatorException : 인증 경로에 대한 트러스트 앵커를 찾을 수 없습니다." u는이에 도움이 될 수 있습니다
인 Vishwa 프라 탑에게

이것은 근본적으로 안전하지 않습니다. 사용하지 마세요.
Lorne의 후작

감사! getUnsafeOkHttpClient()Kotlin 에서 메소드 를 다시 작성하십시오 : stackoverflow.com/a/60507560/2914140 .
CoolMind

11

아주 오래된 게시물에 답장을 보냅니다. 그러나 어쩌면 그것은 초보자에게 도움이 될 것입니다.

설명 : 아무도 설명 쓰레기를 원하지 않는다는 것을 안다. 오히려 해결책. 그러나 하나의 라이너에서 로컬 컴퓨터에서 컴퓨터를 신뢰하지 않는 원격 컴퓨터로 서비스에 액세스하려고합니다. 원격 서버로부터 신뢰를 얻어야합니다.

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

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

단계 :

앱을 등록하려면 .keystore 확장 파일이 필요합니다. .keystore 파일을 만드는 방법을 모른다면; 다음 섹션 .keystore 파일 만들기 를 따르 거나 다음 섹션으로 건너 뛰십시오 .Apk 파일 서명

.keystore 파일 작성

Android Studio를 엽니 다. 최상위 메뉴 빌드> 서명 된 APK 생성을 클릭하십시오. 다음 창에서 새로 작성 ... 단추를 클릭하십시오 . 새 창에서 모든 필드에 데이터를 입력하십시오. 내가 추천하는 두 개의 Password 필드는 동일한 암호를 가져야합니다. 다른 비밀번호를 사용하지 마십시오. 또한 최상위 필드 키 저장 경로 의 저장 경로를 기억하십시오 . 모든 필드를 입력 한 후 확인 버튼을 클릭하십시오.

APK 파일 서명

이제 방금 만든 .keystore 파일로 서명 된 앱을 빌드해야합니다. 다음과 같이하세요

  1. 빌드> 프로젝트 정리, 청소가 끝날 때까지 기다리십시오
  2. 빌드> 서명 된 APK 생성
  3. 클릭 Choose existing...버튼
  4. .keystore 파일 작성 섹션 에서 방금 작성한 .keystore 파일을 선택하십시오.
  5. .keystore 파일 작성 섹션 에서 작성 하는 동안 작성한 것과 동일한 비밀번호를 입력 하십시오. Key store passwordKey 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. 연결된 Wi-Fi를 길게 누르고 Modify network
  3. 필드 Advanced options가 보이지 않으면를 클릭하십시오Proxy Hostname
  4. (가)에서 Proxy Hostname호스트 IP를 입력하거나 이름을 당신은 연결하려는. 일반적인 준비 서버의 이름은 다음과 같습니다.stg.api.mygoodcompany.com
  5. 포트의 경우 예를 들어 4 자리 포트 번호를 입력하십시오. 9502
  6. 히트 Save버튼을

마지막 중지 :

우리가 서명 된 APK 파일을 생성 기억 서명 APK 파일 섹션을 참조하십시오. 이제 해당 APK 파일을 설치해야합니다.

  1. 터미널을 열고 서명 된 apk 파일 폴더로 변경
  2. Android 기기를 컴퓨터에 연결
  3. 안드로이드 장치에서 이전에 설치된 apk 파일을 제거하십시오.
  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

문제가 해결되기를 바랍니다. 그렇지 않은 경우 의견을 남겨주세요.

살람!


4

내가 받고있는 오류 메시지는 비슷했지만 그 이유는 자체 서명 된 인증서가 만료 되었기 때문입니다. openssl 클라이언트를 시도했을 때 firefox에서 인증서 대화 상자를 확인할 때 간과 한 이유가 있습니다.

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


1
인증서가 만료되면 여러 표준에 따라 유효하지 않습니다. 사용자 정의 TrustManager를 사용하고 다른 기준 세트를 사용해도됩니다. 그러나 즉시 사용할 수있는 작업입니다.
jww

4

Android 클라이언트에서 Kurento 서버에 연결하는 동안 동일한 문제가 발생했습니다. Kurento 서버는 jks 인증서를 사용하므로 pem을 변환해야했습니다. 변환 입력으로 cert.pem 파일을 사용했으며 이러한 오류가 발생했습니다. 그러나 cert.pem 대신 fullchain.pem 을 사용하면 모든 것이 정상입니다.


3

https://www.ssllabs.com/ssltest/ 를 사용 하여 도메인을 테스트 하십시오 .

Kotlin 의 Shihab Uddin 솔루션 .

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

companion object {

    private val gson: Gson
    private val retrofit: Retrofit

    init {

        val okHttpClient = getUnsafeOkHttpClient() // OkHttpClient().newBuilder()
            .build()

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

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

    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)
        }
}

2

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

전의. 1. Root.crt 2. Inter.crt 3. myCrt.crt

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

(여기서 myCrt.crt를 무시했습니다)

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


우리도 같은 문제가있었습니다. 중급 증명서가 누락되었습니다
Nidhin Chandran

1

트러스트 앵커 오류는 여러 가지 이유로 발생할 수 있습니다. 나를 위해 단순히 내가 https://example.com/대신 액세스하려고했습니다 https://www.example.com/.

따라서 자신의 Trust Manager 구축을 시작하기 전에 URL을 다시 확인하고 싶을 수 있습니다.


0

진저 브레드 폰에서는 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)
}

기본적으로 사용자 지정 인증서를 신뢰하도록 설정했습니다. 이것이 실패하면 보안을 비활성화합니다. 이것은 최선의 선택은 아니지만, 오래되고 버그가 많은 전화로 아는 유일한 선택입니다.

이 샘플 코드는 Java로 쉽게 번역 될 수 있습니다.


누군가가 그것을 필요로하는 경우 안드로이드 2.3.x에 대한 솔루션, stackoverflow.com/a/46465722/7125370
Newbie009

0

제 경우에는 Android 8.0으로 업데이트 한 후에 발생했습니다. Android가 신뢰로 설정 한 자체 서명 인증서는 서명 알고리즘 SHA1withRSA를 사용하고있었습니다. 서명 알고리즘 SHA256withRSA를 사용하여 새 인증서로 전환하면 문제가 해결되었습니다.


0

모든 인증서를 신뢰할 필요는 없지만 내 경우에는 자체 서명 된 인증서가있는 더러운 디버깅 환경에 문제가 있었고 더러운 솔루션이 필요했습니다.

내가해야 할 일은 초기화를 변경하는 것이 었습니다. 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 {
    }
} };

이것이 유용하게되기를 바랍니다.


내가 찾고 싶었어! 감사합니다
oxied

오류가 발생했습니다 Hostname '192.168.0.16' was not verified. 로컬 디버거 (IIS Express)를 통해 webapi를 테스트하고 있습니다. 이 문제를 해결하는 방법에 대한 아이디어가 있습니까? 감사합니다 :)
Sam

1
이것은 근본적으로 안전하지 않습니다. 사용하지 마세요.
Lorne의 후작

0

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

Kotlin으로 구현 된 응용 프로그램에 적용된 솔루션을 여기에서 공유합니다.

먼저 다음 웹 사이트 를 사용하여 인증서 및 유효성에 대한 정보를 얻는 것이 좋습니다.

Android 기본 신뢰 저장소 에서 '허용 된 발급자' 로 표시되지 않는 경우 해당 인증서를 가져 와서 애플리케이션에 통합하여 사용자 정의 신뢰 저장소를 작성해야합니다.

필자의 경우 이상적인 솔루션 은 사용자 정의와 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)

    }

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

이것이 누군가를 도울 수 있기를 바랍니다.


0

나는 이것이 매우 오래된 기사라는 것을 알고 있지만 신뢰 앵커 문제를 해결하려고 할 때이 기사를 보았습니다. 어떻게 수정했는지 게시했습니다. 루트 CA를 사전 설치 한 경우 매니페스트에 구성을 추가해야합니다.

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


API 24 이상 만
BekaBot

@BekaBot-이것은 아마도 사실이지만 문서 23 이하에 따르면 기본적으로 사용자 인증서를 신뢰합니다 기본적으로 모든 앱의 보안 연결 (TLS 및 HTTPS와 같은 프로토콜 사용)은 사전 설치된 시스템 CA 및 Android 6.0을 대상으로하는 앱을 신뢰합니다 (API 레벨 23) 이하는 기본적으로 사용자가 추가 한 CA 저장소를 신뢰합니다.
GR Envoy

-1
**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);

-2

나는 또한 같은 문제에 직면했다. http와 같은 hhtps를 제거합니다.

final public static String ROOT_URL = "https://example.com";final public static String ROOT_URL = "http://example.com";

마지막으로이 문제를 해결했습니다.


분명히 이것은 SSL 보안을 방정식에서 제거하는 것입니다. 프로덕션 환경에는 나쁜 생각 일 것입니다.
Dragonthoughts

이것은 실제로 솔루션이 아니며 SSL 보안을 제거합니다.
오메가
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.