4

私は、ajax リクエストを受け入れて応答する https サーバーを Java で作成中です。これはすべて http 接続で機能していますが、https の設定が難しいことがわかっています。openssl を使用すると、サーバーにアクセスして期待どおりの応答を得ることができます。 openssl s_client -connect localhost:5001ただし、ブラウザーからの ajax 呼び出しは失敗します。ここからどこへ行けばいいのかわからない。

これは、試行された 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();
        }
    }
}

これは以下で実行されています:

java -Djavax.net.ssl.keyStore=mySrvKeystore -Djavax.net.ssl.keyStorePassword=123456 myApp

また、デバッグ オプションで実行すると、mySrvKeystore が適切に使用されているように見えます。

アップデート

デバッグ出力からの詳細情報を次に示します。

*** 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()
4

1 に答える 1

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()

Sun の古い例については、Using AES in JSSEを参照してください。

一般に、最新のブラウザはTLS_RSA_WITH_AES_128_CBC_SHAのような暗号スイートで接続できます

于 2012-06-03T20:53:49.020 に答える