2016-10-08 1 views
1

브라우저와 java7이 영향을받지 않는 이유는 SSL 정보의 일부로 서버 이름 표시 -SNI를 보내기 때문입니다. 따라서 apache는 SSL 핸드 셰이크를 시작하기 전에 가상 호스트가 사용할 호스트를 알고 적절한 인증서를 반환합니다. Java 6은 SNI를 지원하지 않습니다. 당신이 코드를 볼 수 있듯이 내 질문은 그래서, 어떻게 확인하고 인증서가 나는 웹 서비스를 소비하는 봄 클라이언트를 만든 6.JAVA 6는 SNI를 지원하지 않습니다. TLS를 통해 SSL 인증서를 확인하고 수락하는 다른 방법은 없습니까?

자바에서 허용 될 수있게 않습니다, 나는 여기, 내 코드

public class classname1 { 

    static { 
     System.setProperty("javax.net.ssl.trustStore", "E://Workspace//keystore"); 
     System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); 
     System.setProperty("https.protocols", "SSLv3"); 
     System.setProperty("https.protocols", "TLSv1"); 

    } 
    static { 

       HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() 
        { 
         public boolean verify(String hostname, SSLSession session) 
         { 
          if (hostname.equals("192.168.10.22")) 
           return true; 
          return false; 
         } 
        }); 
      } 

    private static void main(String[] args) { 
     try { 
      SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance(); 
      SOAPConnection soapConnection = soapConnectionFactory.createConnection(); 

      String url = "https://192.168.10.22/getInformationSearch.asmx?wsdl"; 
      SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url); 
      printSOAPResponse(soapResponse); 
      soapConnection.close(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    private static SOAPMessage createSOAPRequest() throws Exception { 
     // ... Code for request, which will be hitted to url 
    } 

    private static void printSOAPResponse(SOAPMessage soapResponse) throws Exception { 
     // ... Code for response, which will fetch information from webservice 
     // URL 
    } 

} 

입니다 두 가지 방법, 1. Request 용 createSOAPRequest() 2. 응답 용 printSOAPResponse(). 요청을 생성하고 HttpsURLConnection.setDefaultHostnameVerifier() 방법 위와 같이이 정적 블록 간다 그 후 소정 url SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url); 해당 요청을 전송할 것이다 라인 아래 main() 방법

를 (URL 이름 위 코드에서 변경된다).

디버거는 다음과 같이 말합니다. ssl 핸드 셰이크에 실패했으며 SSL 피어가 잘못 종료되었습니다. 자바 6에서만 발생하지만이 코드는 자바 7/8에서 제대로 작동합니다. 대신 정적 블록의

, 나는 자바 6

HostnameVerifier hv = new HostnameVerifier() { 
       public boolean verify(String urlHostName, 
         SSLSession session) { 
        return true; 
       } 
      }; 

코드 아래에 시도하지만 어쨌든 작동하지 않습니다!

다음 jar xercesImpl.jar, saaj-api.jar, saaj-impl.jar, spring-ws-core-1.5.6.jar, spring-ws-security-1.5.6.jar 및 인증서를 사용하고 있습니다. 이 SSL 도메인은 keystore로 가져 왔고 java7/8에서 작동하므로 truststore에 문제가 없습니다. (나는 java 6과 7의 keytool을 사용하여 2 개의 인증서를 만들었고, 둘 다 java7/8에서는 제대로 작동하지만 6에서는 작동하지 않는다.)

나는이 thread을 따라 갔지만 제대로 작동하지는 않는다. 그래서 인증서를 확인하고 자바 6 환경에서 응답을 얻는 다른 방법이 있습니까, 아니면 JAR을 변경해야합니까?

답변

1

SNI없이 연결할 수 있도록 서버가 구성되지 않은 경우에는 작업을 수행 할 수 없습니다.

SNI가 없으면 까지 서버가 SSL 연결이 설정된 후까지 원하는 가상 호스트를 알 수 없습니다.

SNI :

는 OpenSSL이있는 경우, 당신은 당신이 SNI를 사용하지 않는 경우 연결하기 위해 제시 한 다른 인증서를 추출, 혹은 실패를 주목하는 the s_client option를 사용할 수의 차이를 확인하려면

echo | openssl s_client -servername www.virtualhost.com -connect 192.168.1.55:443 | openssl x509 -text 

192.168.1.55을 서버의 실제 IP 주소로 바꾸고 www.virtualhost.com을 연결할 가상 호스트의 호스트 이름으로 바꿉니다. 파이프 라인 앞에 echo 명령을 붙이면 입력 대기 중일 때 openssl이 멈추지 않습니다. SNI없이

는 : SNI없이

echo | openssl s_client -connect 192.168.1.55:443 | openssl x509 -text 

, 당신은 완전히 다른 인증서를 볼 수 있습니다, 또는 당신은 연결 오류가 발생할 수 있습니다.

1

이미 언급했듯이 Java 6는 SNI를 지원하지 않습니다. 그러나 SNI 누락 문제는 인증서를 확인하는 것뿐만 아니라 (서버가 잘못된 인증서를 전송하기 때문에) 서버 구성에 따라 SNI 확장이 없거나 가리 키지 않는 경우 서버에서 핸드 셰이크 오류가 발생합니다. 서버에서 사용할 수있는 호스트 이름. 그리고 이것은 분명히 여기에 있습니다 :

... ssl 핸드 셰이크가 실패하고 SSL 피어가 잘못 종료되었습니다. 자바 6에서만 발생하지만이 코드는 자바 7/8에서 제대로 작동합니다.

클라이언트가 인증서를 확인하기 전에 오류가 발생하기 때문에 시도한 것처럼 인증서 유효성 검사를 변경하는 것은 전혀 도움이되지 않습니다. 즉, 특정 서버와 통신하려는 경우 클라이언트에서 SNI를 지원해야합니다.

관련 문제