2013-10-31 2 views
3

GET 및 POST 요청을 HTTPS를 통해 보안 웹 서비스에 보내는 Javafx 응용 프로그램이 있습니다. 웹 서비스를 호스팅하는 서버의 SSL 설정은 단방향 SSL입니다. 즉, Javafx 애플리케이션이 서버의 신원을 확인하지만 서버가 씩 (thick) 클라이언트의 신원을 확인하지 않습니다.JavaFX 응용 프로그램에서 HTTPS URL에 연결하는 방법

응용 프로그램 서버는 인증서 (외부 기관에서 서명 한)가있는 F5 뒤에 있습니다.

브라우저의 경우 브라우저 자체가 서버의 ID를 확인하고 사용자에게 관련 경고를 표시하므로 문제가되지 않습니다. 하지만 두꺼운 클라이언트의 경우 요청을 보내기 전에 서버의 ID를 확인하는 방법을 모르겠습니다. Javafx 애플리케이션에서이 문제를 처리하는 방법을 알려주십시오.

이 질문과 관련하여 이전에 herehere과 같은 질문을했지만 도움이되지 않았습니다. 그러니이 주제에 대한 제한된 지식을 용서해주십시오.

도움을 주시면 감사하겠습니다.

+0

(자바 버전) 알려진 CA와 _valid_에서 발급 한 서버 인증서 (가 다양한 측면을 포함하는 경우 : PKIX 체인을 이전하지 날짜

  • 서버에 연결하는 코드를 사용하여 CN, 확장 등) 모든 것이 추가 코드없이 작동해야합니다. 일반 HttpsUrlConnection이 작업을 수행합니다. – user1516873

  • +0

    그리고 HttpsUrl 연결은 모든 것을 검사하므로 잘못된 인증서가있는 사이트에 https 프로토콜로 연결할 수 없습니다. 실제로 오래된 루트 CA 인증서가있는 이전 Java 버전을 사용하는 경우 유효한 인증서가있는 사이트에 연결할 수는 없지만 새 CA로 발급되는 것은 Java가 내부 키 저장소에 없기 때문입니다. – user1516873

    +0

    ssl/https 및 작동 원리에 대해 자세히 알고 싶다면 http://www.zytrax.com/tech/survival/ssl.html – user1516873

    답변

    5

    인증서가 Firefox/java에서 작동하지 않는 경우 대부분 발급자는 Firefox/java에서 알 수 없습니다. 그것이 작동되도록하는 방법

    는 :

    1. 은 서버의 전체 인증서 체인을 가져옵니다. Firefox로 할 수 있습니다. 인증서보기 -> 세부 정보 -> .pem 파일로 내 보냅니다. 당신의 케이스 체인에는 최소한 2 개의 인증서 (cerver cert와 CA cert, CA 가능한 자체 서명 또는 아닐 수도 있음)가 포함됩니다. CA 인증서를 .pem 파일로 내 보냅니다.

    2. 이제 Java가 다양한 방법으로 CA를 신뢰하도록 할 수 있습니다. 예를 들어 jre cacerts에 CA 인증서를 추가하거나 HttpsURLConnection에 대한 사용자 지정 SSLContext를 만들 수 있습니다.

    3. DNS 또는 기타 호스트 수정을 수행하는 경우이를 롤백하십시오. 연결 주소는 인증서 CN과 일치해야하며 와일드 카드를 포함해야합니다.

      public void test() throws Exception { 
          URL u = new URL(
            "https://my-server.com/my-webservices/data"); 
          HttpsURLConnection http = (HttpsURLConnection) u.openConnection(); 
          http.setSSLSocketFactory(createSSLContext().getSocketFactory()); 
          http.setAllowUserInteraction(true); 
          http.setRequestMethod("GET"); 
          http.connect(); 
      
          InputStream is = http.getInputStream(); 
          BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 
          StringBuilder stringBuilder = new StringBuilder(); 
          String line = null; 
          while ((line = reader.readLine()) != null) 
          { 
           stringBuilder.append(line 
             + "\n"); 
          } 
          System.out.println(stringBuilder.toString()); 
      
      } 
      
      private SSLContext createSSLContext() throws Exception { 
          CertificateFactory cf = CertificateFactory.getInstance("X.509"); 
          FileInputStream in = new FileInputStream("path_to_ca_file.pem"); 
          KeyStore trustStore = KeyStore.getInstance("JKS"); 
          trustStore.load(null); 
          try { 
           X509Certificate cacert = (X509Certificate) cf.generateCertificate(in); 
           trustStore.setCertificateEntry("ca", cacert); 
          } finally { 
           IOUtils.closeQuietly(in); 
          } 
      
          TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); 
          tmf.init(trustStore); 
      
          SSLContext sslContext = SSLContext.getInstance("SSL"); 
          sslContext.init(null, tmf.getTrustManagers(), new SecureRandom()); 
          return sslContext; 
      } 
      
    +1

    답변 해 주셔서 감사합니다 [user1516873] (http://stackoverflow.com/users/1516873/user1516873). 인증서가 만료되면 업데이트가 필요하기 때문에 로컬에 인증서를 패키징하는 것을 피하려고합니다. 나는 응용 프로그램이 항상 서버의 인증서로 작동한다면, 그 소리가 가장 좋은 해결책이라고 생각합니다. 이것을 달성 할 수있는 방법이 있습니까? – Aspirant

    +2

    예, 응용 프로그램은 서버에서 가져온 인증서로 작업 할 수 있지만 한 가지 종류의 공격 스니핑 만 제거합니다. MITM http://en.wikipedia.org/wiki/Man-in-the-middle_attack 및 etc/hosts 다시 쓰기는 여전히 해당 종류의 https에 적용될 수 있습니다. – user1516873

    +0

    위의 코드 에서처럼 SSLSocketFactory를 설정하지 않아도됩니다. 감사. httpSETSSLSocketFactory (createSSLContext(). getSocketFactory()); – Aspirant