2012-05-22 68 views
4

我正在編寫一個用java接受並響應ajax請求的https服務器。我有這一切與http連接工作,但https證明難以建立。如果我使用openssl,我可以打到服務器並按預期得到響應:openssl s_client -connect localhost:5001但來自瀏覽器的ajax調用失敗。我不確定該從哪裏出發。Java https有握手問題

這是來自服務器的attemped Ajax調用後的堆棧跟蹤:

javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake 
at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source) 
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source) 
at sun.security.ssl.SSLSocketImpl.writeRecord(Unknown Source) 
at sun.security.ssl.AppOutputStream.write(Unknown Source) 
at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source) 
at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source) 
at sun.nio.cs.StreamEncoder.implFlush(Unknown Source) 
at sun.nio.cs.StreamEncoder.flush(Unknown Source) 
at java.io.OutputStreamWriter.flush(Unknown Source) 
at java.io.BufferedWriter.flush(Unknown Source) 
at com.myDomain.HttpsServer.main(HttpsServer.java:223) 
Caused by: java.io.EOFException: SSL peer shut down incorrectly 
at sun.security.ssl.InputRecord.read(Unknown Source) 
... 11 more 

AJAX調用:

var command, req; 
    command = { 
    command: "getStatus", 
    }; 
    command = JSON.stringify(command); 
    req = $.ajax("https://localhost:5001", { 
    data: command, 
    dataType: "jsonp", 
    timeout: 1000 
    }); 

Java服務器:

private static SSLServerSocket createSSLSocket(){ 
    SSLServerSocketFactory sslServerSocketFactory = 
     (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); 
    try{ 
     SSLServerSocket sslSocket = 
     (SSLServerSocket) sslServerSocketFactory.createServerSocket(port, 10, InetAddress.getByName("127.0.0.1")); 
     return sslSocket; 
    } catch (Exception e){ 
     e.printStackTrace(); 
    } 
    return null; 
} 

public static void main (String args[]) throws Exception { 
    SSLServerSocket sslSocket; 
    sslSocket = createSSLSocket(); 

    while(running) { 
     SSLSocket connected = (SSLSocket) sslSocket.accept(); 
     try{ 
     BufferedWriter w = new BufferedWriter(
      new outputStreamWriter(connected.getOutputStream())); 
      BufferedReader r = new BufferedReader(
       new InputStreamReader(connected.getInputStream())); 
      w.write("HTTP/1.0 200 OK"); 
      w.write("foo"); 
      w.newLine(); 
      w.flush(); //THIS IS WHERE THE ACTUAL EXCEPTION IS THROWN (LINE 223) 
      w.close(); 
      r.close(); 
      connected.close(); 
     } catch (Exception e){ 
     e.printStackTrace(); 
     } 
    } 
} 

這正與運行:

​​

它看起來像正在使用mySrvKeystore適當時與調試選項來完成。

UPDATE

這裏是從調試輸出一些信息:

*** ECDH ServerKeyExchange 
Server key: Sun EC public key, 256 bits 
    public x coord:  59120686551233854673577061225846672012454441193286172303206804252170042475984 
    public y coord: 64356797475544123011351526783519675095229374542555548418334080869325161950574 
    parameters: secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7) 
*** ServerHelloDone 
main, WRITE: TLSv1 Handshake, length = 1317 
main, received EOFException: error 
main, handling exception: javax.net.ssl.SSLHandshakeException: Remote host closed connection  during handshake 
%% Invalidated: [Session-1, TLS_ECDHE_RSA_WITH_RC4_128_SHA] 
main, SEND TLSv1 ALERT: fatal, description = handshake_failure 
main, WRITE: TLSv1 Alert, length = 2 
main, called closeSocket() 
+0

是否在所有瀏覽器失效密碼套件連接呢? 有一個相同的堆棧跟蹤的問題:http://stackoverflow.com/questions/4827190/exception-at-start-of-request-clientauth-ssl – Serxipc

+0

你能找到任何與這個問題?謝謝 –

+0

看起來這是一個特定於chrome的問題。檢查這個傢伙:http://stackoverflow.com/questions/7535154/chrome-closing-connection-on-handshake-with-java-ssl-server –

回答

0

它可以是棘手確定這樣的握手失敗。嘗試啓用SSL/TLS調試使用:

-Djavax.net.debug=true 

您可能還需要增加一個信任存儲在服務器上:

-Djavax.net.ssl.trustStore=mySrvKeystore 

的密碼套件TLS_ECDHE_RSA_WITH_RC4_128_SHA可能不被你的瀏覽器支持正在使用。它可能是客戶端/服務器嘗試協商幾個,並在最後一個失敗。您可以使用服務器上打印出您啓用的密碼套件:

String[] cipherSuites = sslSocket.getEnabledCipherSuites(); 
for (int x = 0; x < cipherSuites.length; x++) { 
    System.out.println(cipherSuites[x]); 
} 

您也可以考慮限制服務器提供使用sslSocket.setEnabledCipherSuites()選擇密碼。

查看Using AES in JSSE瞭解Sun的一些舊例子。

一般一個現代瀏覽器都可以用類似TLS_RSA_WITH_AES_128_CBC_SHA