2012-01-01 3 views

답변

15

당신은 기본 트러스트 매니저를 감싸는 CertificiateExpiredException를 잡아 그것을 무시한 TrustManager를 구축해야한다.

참고 : this answer에 설명 된대로, 이것이 안전한지 여부는 구현에 따라 크게 다릅니다. 특히, 다른 모든 것이 제대로 검사 된 후에 마지막으로 수행 된 날짜 유효성 검사에 의존합니다. 이 라인을 따라

뭔가 일을해야 뭔가가 인증서에 문제가 있습니다 때

TrustManagerFactory tmf = TrustManagerFactory.getInstance(
    TrustManagerFactory.getDefaultAlgorithm()); 
// Initialise the TMF as you normally would, for example: 
tmf.init((KeyStore)null); 

TrustManager[] trustManagers = tmf.getTrustManagers(); 
final X509TrustManager origTrustmanager = (X509TrustManager)trustManagers[0]; 

TrustManager[] wrappedTrustManagers = new TrustManager[]{ 
    new X509TrustManager() { 
     public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
      return origTrustmanager.getAcceptedIssuers(); 
     } 

     public void checkClientTrusted(X509Certificate[] certs, String authType) { 
      origTrustmanager.checkClientTrusted(certs, authType); 
     } 

     public void checkServerTrusted(X509Certificate[] certs, String authType) { 
      try { 
       origTrustmanager.checkServerTrusted(certs, authType); 
      } catch (CertificateExpiredException e) {} 
     } 
    } 
}; 

SSLContext sc = SSLContext.getInstance("TLS"); 
sc.init(null, wrappedTrustManagers, null); 
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 

신뢰 관리자는 CertificateException의 (자세한 내용은 서브 클래스를 참조)를 던져. 너가 붙잡거나 무시하고 싶은 무슨을 안에 명확 하 있으 십시요. 잠재적으로 던져지기 전에 확인해야하는 모든 것을 검사해야합니다. 그렇지 않으면 수동으로 유효성을 검사해야합니다. 이보다 더 편한 어떤 것도 (특히 아무것도하지 않고 아무 예외도 던지지 않음) 익명의 암호 스위트를 사용하거나 인증을 무시하는 것과 거의 같은 인증서 확인과 유효성 검사를 무시할 것입니다. 이는 SSL/TLS를 사용하는 보안 목적을 무효화합니다 (만료일에 조금 더 유연함과 대조적으로).

+0

이 코드는 전혀 작동하지 않습니다. tmf.getTrustManagers()가 실행될 때 "TrustManagerFactory가 초기화되지 않았습니다."라는 예외가 발생합니다. 나중에 게시하기 전에 코드를 테스트하십시오. 나는 그 문제를 풀 수있는 방법을 찾아내는 데 1 시간 이상을 보냈다. – AndroidDev

+1

@AndroidDev, 죄송합니다, 나는 OP가 TMF가 정상적으로 초기화되어야한다는 것을 알고 있다고 가정하고 있었지만, 아마 맞을 것입니다. 확실하지 않습니다. (방금 편집했습니다.) – Bruno

+0

항상 javax.net.ssl.SSLHandshakeException : 동료가 닫은 연결 –

2

만료 된 인증서를 무시할 사용자 지정 X509 유효성 검사기를 만들어야합니다. 사실, 검사는 수행되지 않습니다. 여기에서 가져온

코드 : http://exampledepot.com/egs/javax.net.ssl/TrustAll.html

// Create a trust manager that does not validate certificate chains 
TrustManager[] trustAllCerts = new TrustManager[]{ 
    new X509TrustManager() { 
     public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
      return null; 
     } 
     public void checkClientTrusted(
      java.security.cert.X509Certificate[] certs, String authType) { 
     } 
     public void checkServerTrusted(
      java.security.cert.X509Certificate[] certs, String authType) { 
     } 
    } 
}; 

// Install the all-trusting trust manager 
try { 
    SSLContext sc = SSLContext.getInstance("SSL"); 
    sc.init(null, trustAllCerts, new java.security.SecureRandom()); 
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 
} catch (Exception e) { 
} 

// Now you can access an https URL without having the certificate in the truststore 
// It should work with expired certificate as well 
try { 
    URL myUrl = new URL("https://www....."); 
} catch (MalformedURLException e) { 
} 
+2

이'TrustManager'처럼 보안 검사를 완전히 불가능하게하는 코드를 복사/붙여 넣기/전파하는 것을 피하십시오. 이것은 SSL/TLS를 사용하는 지점을 처음부터 무의미하게 만듭니다. – Bruno

+0

일부 휴대 장치에서 배터리를 제거하면 날짜가 1980과 같은 이전 날짜로 재설정되어 만료 날짜로 인해 SSL 인증서가 실패합니다. 이로 인해 앱이 실패 할 수 있으며 만료 된 인증서로도 앱이 계속 작동하는 것이 중요 할 경우 만료일을 무시하는 것이 중요합니다. – AndroidDev

+0

@AndroidDev 귀하의 비판이 Bruno의 의견을 언급하기위한 것이면 모든 인증서와 오래된 신뢰할 수있는 인증서를 수락하는 것 사이에 큰 차이가 있음을 알려드립니다. 게다가 심각한 사용자는 여러 가지 이유로 날짜를 조정합니다. –

1

이 문제를 해결하기 위해 사용자 지정 TrustManager를 작성했습니다.이 메시지는 https://gist.github.com/divergentdave/9a68d820e3610513bd4fcdc4ae5f91a1에서 볼 수 있습니다. 이 TrustManager는 문제가되는 X509Certificate를 다른 클래스에 래핑하여 만료 검사를 비활성화하고 다른 모든 유효성 검사를 그대로 유지합니다. (즉, 호스트 이름과 일치하고, 신뢰할 수있는 CA에 체인을 연결하고, 유효한 서명 등)

+0

좋은 예입니다. ** checkValidity ** 메소드가 호출되지 않았 음을 알았습니다. 방아쇠 된 유일한 콜백은 ** getEncoded ** 및 ** getPublicKey **입니다.내가 로컬 키 저장소를 사용하고 고정 된 인증서가로드되어 있다는 사실과 관련이 있는지 확실하지 않은 경우? – jayeffkay

+0

@jayeffkay 나는 이것을 로컬에서 시도해 보았고 몇몇 메소드가 호출되는 것을 보았다. 'checkValidity'가 호출되는 것을 보았습니다. 그러나 라인 번호 중단 점 대신 메쏘드 중단 점을 설정해야했습니다. 그 메쏘드에는 빈 시체가 있기 때문입니다. 고정 된 인증서가 차이를 만들지는 모르지만 자체 서명 된 인증서를 동작을 변경할 수있는 서버 인증서 (리프 인증서가 아닌)로 사용하는 경우 확실하지 않습니다. TLS 서버의 공개 키가 신뢰 저장소의 자체 서명 된 인증서의 공개 키와 같으면 나머지 검사는 유용하지 않습니다. (무슨 일이 일어날 지 테스트하지 않았다) – dncook

관련 문제