5

Tôi đang cố gắng tiêu thụ một ws an toàn với auth cơ bản. Tôi đã không nhập bất kỳ chứng chỉ nào vào kho khóa của mình. Khi tôi sử dụng plugin chrome Advance Rest client để kiểm tra nó (sử dụng auth cơ bản với tên người dùng được mã hóa base64: pass). Tôi có thể thấy phản hồi lại. Càng xa càng tốt. Nhưng khi tôi phát triển mã Java để tiêu thụ ws này, tôi nhận SSL thất bại handsake:Spring RestTemplate: SSL handshake failure

org.springframework.web.client.ResourceAccessException: I/O error: 
Received fatal alert: handshake_failure; nested exception is 
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure 
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:453) 
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:401) 
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:377) 
at test.Rest.main(Rest.java:37) Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure 
at sun.security.ssl.Alerts.getSSLException(Unknown Source) 
at sun.security.ssl.Alerts.getSSLException(Unknown Source) 

Câu hỏi của tôi là: nếu vấn đề là bởi vì tôi đã không nhập khẩu cert để keystore của tôi, sau đó cả hai mã Java và plugin nên không làm việc cùng nhau. Ở đây, plugin hoạt động nhưng mã của tôi thì không. Lý do là gì? Có lỗi gì với mã của tôi?

Bellow là mã của tôi

RestTemplate restTemplate = new RestTemplate();   
String plainCreds = "username:pass"; 
byte[] plainCredsBytes = plainCreds.getBytes(Charset.forName("US-ASCII"));  
byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes); 
String base64Creds = new String(base64CredsBytes); 

HttpHeaders headers = new HttpHeaders(); 
headers.add("Authorization", "Basic " + base64Creds); 

ResponseEntity<String> response = 
      restTemplate.exchange("https://url",HttpMethod.GET,new 
            HttpEntity(headers),String.class); 

Dưới đây là liên kết để đăng nhập tập tin: (Tôi có thay thế máy chủ tên của tôi bằng cách XXXXXX) http://www.filedropper.com/ssllog

Sau khi chạy: openssl s_client -showcerts -tls1 - máy chủ kết nối: cổng

WARNING: can't open config file: /usr/local/ssl/openssl.cnf 
CONNECTED(00000164) 
8088:error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number:.\ssl\s3_pkt.c:362: 
--- 
no peer certificate available 
--- 
No client certificate CA names sent 
--- 
SSL handshake has read 5 bytes and written 0 bytes 
--- 
New, (NONE), Cipher is (NONE) 
Secure Renegotiation IS NOT supported 
Compression: NONE 
Expansion: NONE 
No ALPN negotiated 
SSL-Session: 
    Protocol : TLSv1 
    Cipher : 0000 
    Session-ID: 
    Session-ID-ctx: 
    Master-Key: 
    Key-Arg : None 
    PSK identity: None 
    PSK identity hint: None 
    SRP username: None 
    Start Time: 1452011344 
    Timeout : 7200 (sec) 
    Verify return code: 0 (ok) 
--- 

và đây là đầu ra khi tôi chạy lệnh openssl s_client -connect server: port

WARNING: can't open config file: /usr/local/ssl/openssl.cnf 
CONNECTED(00000164) 
depth=0 C = US, ST = "XXXXXX", L = XXXXXX, O = XXXXXX, OU = xxxxx, CN = XXXXXXXXX.test.intranet, emailAddress = [email protected] 
verify error:num=20:unable to get local issuer certificate 
verify return:1 
depth=0 C = US, ST = "XXXXXXX ", L = XXXXX, O = XXXXXX, OU = xxxxxx, CN = XXXXXXXXX.test.intranet, emailAddress = [email protected] 
verify error:num=21:unable to verify the first certificate 
verify return:1 
--- 
Certificate chain 
0 s:/C=US/ST=XXXXXXX /L=XXXXX/O=XXXXXX/OU=XXXXX/CN=XXXXXX.test.intranet/[email protected] 
    i:/DC=intranet/DC=xxxx/CN=XXXXXX DEV Issuing CA 
--- 
Server certificate 
-----BEGIN CERTIFICATE----- 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 
XXXXX..... 
-----END CERTIFICATE----- 
subject=/C=US/ST=XXXXXXX /L=XXXXX/O=XXXXXX/OU=XXXXX/CN=XXXXXX.test.intranet/[email protected] 
issuer=/DC=intranet/DC=XXX/CN=XXXXX DEV Issuing CA 
--- 
No client certificate CA names sent 
Peer signing digest: SHA512 
Server Temp Key: XXXXX, P-256, 256 bits 
--- 
SSL handshake has read 1895 bytes and written 443 bytes 
--- 
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256 
Server public key is 2048 bit 
Secure Renegotiation IS supported 
Compression: NONE 
Expansion: NONE 
No ALPN negotiated 
SSL-Session: 
    Protocol : TLSv1.2 
    Cipher : ECDHE-RSA-AES128-GCM-SHA256 
    Session-ID: 568BF22A5CDBF103155264BBC056B272168AE0777CBC10F055705EB2DD907E5A 
    Session-ID-ctx: 
    Master-Key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 
    Key-Arg : None 
    PSK identity: None 
    PSK identity hint: None 
    SRP username: None 
    Start Time: 1452012074 
    Timeout : 300 (sec) 
    Verify return code: 21 (unable to verify the first certificate) 
--- 
read:errno=0 
+0

Chrome và ứng dụng của bạn có thể sử dụng Java khác nhau và do đó có các cài đặt khác nhau. Ngay cả khi Java là như nhau có triệu lý do tại sao nó không hoạt động. Tuy nhiên nó là khởi đầu tốt mà nó hoạt động từ Chrome. Bật gỡ lỗi SSL của JVM, ví dụ: thêm '-Djavax.net.debug = ssl: handshake: verbose' và thêm đầu vào vào câu hỏi của bạn, Các đối số gỡ lỗi bổ sung có sẵn tại đây http://docs.oracle.com/javase/7/ docs/technotes/guides/security/jsse/JSSERefGuide.html # Debug –

+0

Tôi sẽ điều tra máy chủ của bạn, vì nhật ký không chứa thông báo 'ServerHello' như thể máy chủ của bạn không chạy SSL. Nếu bạn có openssl thử kết nối ở đó với 'openssl s_client -showcerts -tls1 -connect [your_host]: [port]'. Xem thêm http://www.smartjava.org/content/how-analyze-java-ssl-errors –

+0

Cảm ơn Michal. Tôi đã thêm đầu ra để chạy openssl. Làm ơn giúp tôi. Tôi mới để ssl và giấy chứng nhận thứ – David

Trả lời

7

Từ javax.net.debug đăng nhập Tôi có thể thấy rằng bạn đang sử dụng Java 7 và máy khách phân giải thành TLSv1. Từ openssl đầu ra rằng máy chủ của bạn không hỗ trợ TLSv1.

TLS ver. 1.1 and 1.2 are disabled in Java 7 by default.

Mặc dù SunJSSE trong bản phát hành Java SE 7 hỗ trợ TLS 1.1 và TLS 1.2, không phải phiên bản được kích hoạt theo mặc định cho các kết nối client. Một số máy chủ không thực hiện đúng khả năng tương thích về phía trước và từ chối nói chuyện với khách hàng TLS 1.1 hoặc TLS 1.2. Đối với khả năng tương tác, SunJSSE không bật TLS 1.1 hoặc TLS 1.2 theo mặc định cho các kết nối của khách hàng .

Enable TLSv1.1 và TLSv1.2 bằng cách:

  1. JVM luận:

    -Dhttps.protocols=TLSv1.2,TLSv1.1,TLSv1 
    
  2. Hoặc thiết lập thuộc tính tương tự từ mã Java:

    System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,TLSv1"); 
    
  3. Hoặc cài đặt JCE Unlimited Strength policy files for Java 7. Tôi không chắc chắn 100% nếu bước này sẽ giải quyết được vấn đề mặc dù nó luôn luôn có giá trị để cài đặt JCE trong khi nó cho phép JVM sử dụng các phiên bản mạnh hơn của các thuật toán hiện có.

CẬP NHẬT 29/Sep/2016:

trật tự đã thay đổi các giao thức từ từ tốt hơn để tồi tệ hơn (TLS ver 1,2-1.) Trong các tùy chọn 1 và 2.

+0

Cảm ơn Michal đã giúp đỡ bệnh nhân của bạn. Chúng tôi phát hiện ra rằng máy chủ lưu trữ các phần còn lại đang sử dụng jdk8 và ứng dụng khách của tôi đang sử dụng jdk7. Vì vậy, chúng tôi đã hạ cấp máy chủ xuống jdk7. Và tôi cũng phải buộc jdk sử dụng TSLv1.2 bằng cách sử dụng -Dhttps.protocols = TLSv1, TLSv1.1, TLSv1.2. Nó hiện đang hoạt động. – David

+0

trước khi cố gắng sử dụng -Dhttps.protocols = TLSv1, TLSv1.1, TLSv1.2. tôi cũng đã cố cài đặt chính sách JCE Unlimited Strength cho jdk7. Tôi đã thay thế các tập tin trong jdk/jre/lib/security bằng các tập tin trong tập tin zip. Nhưng nó không hoạt động. – David

+0

Bạn được chào đón David và cảm ơn bạn đã phản hồi và đánh giá cao của bạn. –

1

Nếu bạn tình cờ sử dụng Java 7, bạn cần nói rõ với Java để sử dụng giao thức TLSv1.2. Đây là một ví dụ sử dụng cấu hình Spring XML.

***In any Spring bean (i.e. a controller)*** 

import org.apache.http.client.HttpClient; 
import org.apache.http.ssl.SSLContexts; 
import org.apache.http.conn.ssl.SSLConnectionSocketFactory; 
import org.apache.http.impl.client.HttpClients; 
import javax.net.ssl.SSLContext; 

@Bean(name="client") 
public HttpClient make() throws NoSuchAlgorithmException, KeyManagementException { 
    SSLContext sslContext = SSLContexts.custom().build(); 
    SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, 
      new String[]{"TLSv1.2", "TLSv1.1"}, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier()); 
    return HttpClients.custom() 
      .setSSLSocketFactory(sslConnectionSocketFactory) 
      .build(); 
} 

***In XML configuration files*** 

<bean id="factory" 
     class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory"> 
    <property name="httpClient" ref="client"/> 
</bean> 
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate"> 
    <property name="requestFactory" ref="factory"/> 
</bean> 

Bạn có thể làm như vậy mà không XML với một cái gì đó như thế này:

RestTemplate restTemplate; 

public HttpClient getHttpClient() throws NoSuchAlgorithmException, KeyManagementException { 
    SSLContext sslContext = SSLContexts.custom().build(); 
    SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, 
      new String[]{"TLSv1.2", "TLSv1.1"}, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier()); 
    return HttpClients.custom() 
      .setSSLSocketFactory(sslConnectionSocketFactory) 
      .build(); 
} 

public void setUp() throws Exception { 
    restTemplate = new RestTemplate(
      new HttpComponentsClientHttpRequestFactory(
        getHttpClient())); 
    ... 
} 
Các vấn đề liên quan