2010-06-28 4 views
17

Android에서 HttpClient를 사용하여 https://someUrl.com/somePath에 연결합니다. 문제는 사이트의 인증서가 someUrl.com이 아닌 * .someUrl.com에 대한 것이므로 SSLException을 얻습니다. 사이트의 일부분에 절름발이가 있습니다. 그렇지만, 제가 고칠 수 없다면, 저는 붙어 있습니다. HttpClient가 긴장을 풀고 인증서를 수락 할 수있는 방법이 있습니까?Android HttpClient - 인증서의 호스트 이름이 일치하지 않았습니다. <example.com>! = <*. example.com>

답변

33

이 내 (편집) 솔루션 :

class MyVerifier extends AbstractVerifier { 

    private final X509HostnameVerifier delegate; 

    public MyVerifier(final X509HostnameVerifier delegate) { 
     this.delegate = delegate; 
    } 

    @Override 
    public void verify(String host, String[] cns, String[] subjectAlts) 
       throws SSLException { 
     boolean ok = false; 
     try { 
      delegate.verify(host, cns, subjectAlts); 
     } catch (SSLException e) { 
      for (String cn : cns) { 
       if (cn.startsWith("*.")) { 
        try { 
          delegate.verify(host, new String[] { 
           cn.substring(2) }, subjectAlts); 
          ok = true; 
        } catch (Exception e1) { } 
       } 
      } 
      if(!ok) throw e; 
     } 
    } 
} 


public DefaultHttpClient getTolerantClient() { 
    DefaultHttpClient client = new DefaultHttpClient(); 
    SSLSocketFactory sslSocketFactory = (SSLSocketFactory) client 
      .getConnectionManager().getSchemeRegistry().getScheme("https") 
      .getSocketFactory(); 
    final X509HostnameVerifier delegate = sslSocketFactory.getHostnameVerifier(); 
    if(!(delegate instanceof MyVerifier)) { 
     sslSocketFactory.setHostnameVerifier(new MyVerifier(delegate)); 
    } 
    return client; 
} 

그것은 와일드 카드 도메인이없는 한 기본 동작을 변경하지 않는 장점을 가지고 있으며,이 경우에 2 부분 도메인 (예 : someUrl.com)이 인증서의 일부인 것처럼 재확인합니다. 그렇지 않으면 원래 예외가 다시 전달됩니다. 이는 진정으로 유효하지 않은 인증서가 여전히 실패 함을 의미합니다. 당신이 웹보기를 사용하는 경우

+0

위의 방법을 사용해 보았습니다.하지만 때때로 스택 오버플로 예외가 발생합니다. verify() 메서드는 결코 재귀를 중지하지 않습니다. 수십만 건의 설치 중 일주일에 약 80 회 정도 발생합니다. 이 문제가 생겼습니까? – user291701

+0

@ user291701 문제를 해결하기 위해 코드를 편집했습니다. 나는 그 문제가 당신이 동일한 공장에서 검증자를 다시 설정하게된다고 생각하기 때문에 어떻게 든 자체 위임을 끝낸다. 더 나은 방법을 찾으면 내 대답을 자유롭게 편집 할 수있다. – noah

+0

어쨌든 '미디어 유형이 지원되지 않아 서버가 요청을 처리 할 수 ​​없습니다.'오류가 발생합니다. 이 이유에 대한 단서를 얻지 못했습니다. –

1

*.someUrl.com을 원하면 someUrl.com/somePath 대신 www.someUrl.com/somePath을 줄 수있는 것 같습니다.

+1

아니 무시 호출합니다. www.someUrl.com someUrl.com로 리디렉션 – noah

+0

나는 그것이 쓸모 없다고 생각합니다. https가 정말로 필요합니까? 나는 그렇게 추측 할 것이다. 그러나 그것은 삶을 훨씬 쉽게 만들 것이다. –

+0

사이트가 리디렉션을하지 않을 때 이것은 훌륭한 일시적인 해결책입니다! –

3

Android의 BouncyCastle이 너무 오래되었으며 와일드 카드 인증서를 인식하지 못합니다.

와일드 카드를 확인하기 위해 고유 한 X509TrustManager를 작성할 수 있습니다.

또는 위험을 수락 할 수있는 경우 인증서 확인을 모두 사용하지 않도록 설정할 수 있습니다. 이 질문을 참조

Self-signed SSL acceptance on Android

+0

실제로 ZZ, 사이트 이름 및 인증서 구조에 대한 OP가 올바른 경우 오류 메시지가 정확합니다. ** someUrl.com *은 www.someUrl.com 및 anything.someUrl과 일치해야합니다. co.kr, * someUrl.com 또는 this.that.someUrl.com이 아닙니다. –

1

단지

webview.clearSslPreferences(); 

는 SSL 오류

관련 문제