2012-09-11 45 views
8

Có ai có thể giúp tôi bắt đầu thực hiện các kết nối HTTP với chỉ dẫn tên máy chủ trong Java không?Chỉ dẫn tên máy chủ (SNI) trên Java

Tôi đang cố gắng yêu cầu nội dung từ trang web mà tôi đang quản trị. Tôi đã sử dụng thư viện HttpClient của Apache, nhưng yêu cầu của tôi về nội dung an toàn không thành công vì trang web chỉ sử dụng SNI cho HTTPS và SNI không được kích hoạt trong DefaultHttpClient. Tôi đã tìm hướng dẫn về cách tiếp cận điều này trong thư viện HttpClient của Apache, nhưng tôi thấy kết thúc với tài liệu này: http://hc.apache.org/httpclient-3.x/sslguide.html, đã lỗi thời (đề cập đến mã khi HttpClient và HttpCore là một phần của gói commons của Apache).

Vì vậy, ... bất kỳ trợ giúp nào?

Trả lời

11

bạn có thể muốn theo dõi https://issues.apache.org/jira/browse/HTTPCLIENT-1119

thi client cơ bản của Java 7 có khả năng để hỗ trợ nó và cho thấy nhiều tính năng thông qua SSLSocketImpl # setHost (gọi bằng sun.net.www.protocol.https.HttpsClient

trên Java 7 sử dụng

new URL("https://cmbntr.sni.velox.ch/").openStream() 

cho đến khi HttpClient-1119 là cố định

+1

Nó đã được sửa ngay, có sẵn trong HttpComponents HttpClient 4.3.2. –

+0

Sử dụng HttpClient 4.3.2 trong Tomcat trên OpenJDK (lên đến phiên bản '1.7.0_111'), SNI sẽ vẫn không thành công. Sau khi chuyển sang Oracle HotSpot ('1.7.0_80'), SNI đã làm việc. Đối với bất kỳ ai phải đối mặt với điều này trên AWS Beanstalk, hãy kiểm tra ebextension này để chuyển JVM sang Oracle: https://gist.github.com/bremeld/6706980 – Sitati

0

Có vẻ như vấn đề này đã được khắc phục trong Java 7.

+1

Cảm ơn. Tôi thấy đó là trường hợp. Tuy nhiên, RFC không cho tôi bất kỳ gợi ý nào về cách đạt được điều này (ngoại trừ việc xây dựng khách hàng của riêng tôi từ đầu). Bất kỳ ý tưởng của một công cụ hiện có hoặc làm thế nào để sử dụng Apache HttpClient cho điều này? – JellicleCat

1

với một sửa chữa ngắn càng de ghi theo: TLS with SNI in Java clients Có thể thêm Hỗ trợ máy chủ SNI vào JDK 7 và sử dụng nó cùng với X509ExtendedKeyManager.

1

gì làm việc đối với tôi là cấu hình ServerName một cách chính xác trong cấu hình Apache:

/etc/apache2/sites-avaible/default

<VirtualHost *:443> 
    ServerName foo.domain.com 
    ... 
</VirtualHost> 

Giống như nói trong https://stackoverflow.com/a/8058839/2088282.

4

Đây là cách tôi đã làm nó trong org.apache.httpcomponents của httpclient v4.3 +

private HttpClientConnectionManager createConnectionManager(final SSLContext ctx) { 
    LOG.info("Creating sslConnectionSocketFactory"); 
    final SSLConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(ctx) { 

     @Override 
     protected void prepareSocket(SSLSocket socket) throws IOException { 
      try { 
       System.out.println("************ setting socket HOST property *************"); 
       PropertyUtils.setProperty(socket, HOST, Constants.SNI_HOST); 
      } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) { 
       LOG.error(ex.getMessage()); 
      } 
      super.prepareSocket(socket); 
     } 

    }; 

    LOG.info("Creating connectionRegistry"); 
    final Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create() 
      .register("https", sslSF) 
      .build(); 

    LOG.info("Creating poolingConnectionManager"); 
    final PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry); 
    connectionManager.setDefaultMaxPerRoute(MAX_CONNECTIONS_PER_ROUTE); 
    connectionManager.setMaxTotal(MAX_CONNECTIONS); 

    return connectionManager; 
} 

Và đây là cách tôi tạo ra HttpClient

final KeyManager[] keyManagers = createKeyManagers(); 
final TrustManager[] trustManagers = createTrustManagers(); 
final SSLContext ctx = createSslContext(keyManagers, trustManagers); 

final HttpClientConnectionManager connectionManager = createConnectionManager(ctx); 

LOG.info("Creating httpClient"); 
HttpClient httpClient = HttpClients 
     .custom() 
     .setConnectionManager(connectionManager) 
     .build(); 
+0

Vui lòng không sử dụng 'SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER'. – Bruno

+0

Một số làm rõ đối với những người có thể tò mò như tôi là: 'PropertyUtils' là từ 'commons-beanutils' ' Chuỗi HOST = "host";' 'Constants.SNI_HOST' là hostname DNS của máy chủ bạn muốn kết nối với. Quan trọng nhất: ** Nhà máy tùy chỉnh không còn cần thiết với httpclient 4.5.2 ** –

+0

@DaanReid - Ý của bạn là "Nhà máy tùy chỉnh không còn cần thiết"? Có triển khai mặc định mà chúng tôi có thể sử dụng hay không. – Shyam

Các vấn đề liên quan