Исключение Apache CXF в связи SSL: SocketTimeOut - PullRequest
8 голосов
/ 13 июля 2011

Так вот в чем дело. У меня есть веб-сервис WSDL, для которого мне нужно делать вызовы SOAP вне моей корпоративной сети. Веб-сервис HTTPS SOAP и требует сертификата клиента. Я сгенерировал клиентский код на Java из wsdl2java, и, похоже, все идет хорошо.

Сейчас я не могу получить ответ от веб-службы через CXF. Рукопожатие SSL, кажется, идет очень хорошо, даже до того момента, когда CXF пытается выполнить HTTP POST, но время ожидания ожидания ответа (показано ниже):

Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: false
Is secure renegotiation: false
*** HelloRequest (empty)
main, SEND TLSv1 ALERT:  warning, description = no_renegotiation
Padded plaintext before ENCRYPTION:  len = 24
0000: 01 64 01 FD 5B 38 03 A6   70 41 57 58 6D 75 60 F7  .d..[8..pAWXmu`.
0010: 93 1F 02 F3 C4 46 01 01                            .....F..
main, WRITE: TLSv1 Alert, length = 24
[Raw write]: length = 29
0000: 15 03 01 00 18 0C 9B DF   1B 60 AB 12 EE C7 CF C9  .........`......
0010: 62 97 A5 5D 5F 14 48 E1   9F AD 8A 08 05           b..]_.H......
main, handling exception: java.net.SocketTimeoutException: Read timed out
main, called close()
main, called closeInternal(true)
main, SEND TLSv1 ALERT:  warning, description = close_notify
Padded plaintext before ENCRYPTION:  len = 24
0000: 01 00 BD 99 7A 7C 72 1F   BB 11 2D AB 3F 53 C9 CD  ....z.r...-.?S..

... continuing on

Теперь, если я использую curl или что-то подобное, я могу получить ответ менее чем за секунду, поэтому я знаю, что веб-служба не виновата. Ниже приведен полный код, необходимый для создания служебного порта, включая настройку с использованием TLS и HTTP-прокси. У меня есть очень простой тест JUnit для его создания и запуска:

public static MYPORT setupTLS(MYPORT port) throws IOException,
        GeneralSecurityException {

    HTTPConduit httpConduit = (HTTPConduit) ClientProxy.getClient(port)
            .getConduit();


    String keyPassword = "password";
    KeyStore keyStore = KeyStore.getInstance("pkcs12");
    URL pkcs12_file = MECTPortFactory.class.getResource(System
            .getProperty("pkcs12.keyFile"));
    InputStream keyFile = pkcs12_file.openStream();
    keyStore.load(keyFile, keyPassword.toCharArray());
    KeyManager[] myKeyManagers = getKeyManagers(keyStore, keyPassword);

    TLSClientParameters tlsCP = new TLSClientParameters();
    tlsCP.setKeyManagers(myKeyManagers);
    tlsCP.setDisableCNCheck(true);
    FiltersType cipher_suite_filter = new FiltersType();
    cipher_suite_filter.getInclude().add("SSL_RSA_WITH_3DES_EDE_CBC_SHA");
    cipher_suite_filter.getExclude().add(".*_DH_anon_.*");
    tlsCP.setCipherSuitesFilter(cipher_suite_filter);
    httpConduit.setTlsClientParameters(tlsCP);
    httpConduit.setClient(getHttpClient());

    return port;
}

private static HTTPClientPolicy getHttpClient() {
    HTTPClientPolicy client_policy = new HTTPClientPolicy();
    client_policy.setProxyServer("PROXY_SERVER_ADDRESS");
    client_policy.setProxyServerPort(8080);
    client_policy.setAutoRedirect(true);
    client_policy.setConnection(ConnectionType.KEEP_ALIVE);
    client_policy.setAllowChunking(true);
    client_policy.setReceiveTimeout(10000);
    return client_policy;
}

private static KeyManager[] getKeyManagers(KeyStore keyStore,
        String keyPassword) throws GeneralSecurityException, IOException {
    String alg = KeyManagerFactory.getDefaultAlgorithm();
    char[] keyPass = keyPassword != null ? keyPassword.toCharArray() : null;
    KeyManagerFactory fac = KeyManagerFactory.getInstance(alg);
    fac.init(keyStore, keyPass);
    return fac.getKeyManagers();
}

Edit:

Я возился с некоторыми настройками клиента, такими как изменение AutoRedirect , AllowChunking и т. Д., Без различий, поэтому я не думаю, что это вызывает ошибки.

Edit2:

Я не получаю ответ от веб-службы. Как устранить неполадки и устранить причину истечения времени ожидания CXF вместо получения ответа?

1 Ответ

8 голосов
/ 13 июля 2011

OMG! Я понял это.

Итак, я прошел через паутину и нашел этот маленький драгоценный камень:

Как настроить SoapUI с аутентификацией сертификата клиента

И это ссылается на очень важное примечание от Oracle / Sun:

Информационное сообщение о проблеме пересмотра безопасности транспортного уровня (TLS)

Приложения, получающие запрос на повторное согласование от партнера, будут ответить в соответствии с типом соединения на месте:

TLSv1: предупреждающее сообщение типа "no_renegotiation (100)" будет отправлено одноранговому узлу, и соединение останется открытым.

затем, далее вниз:

Повторное согласование можно повторно включить для тех приложений, которым оно необходимо, установив новое системное свойство sun.security.ssl.allowUnsafeRenegotiation в true до инициализации библиотеки JSSE. Есть несколько способов установить это свойство:

  1. Командная строка:

    % java -Dsun.security.ssl.allowUnsafeRenegotiation=true Main

  2. Панель управления Java (Java-плагин / Java Web Start) - среда выполнения.

  3. В заявке:

    java.lang.System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", true);

Обратите внимание, что повторное согласование TLS / SSL не произойдет, если оба клиент и сервер включили повторные переговоры.

Так долго и коротко? System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true");

И все такое. Просто. Работа.

...