Удаленный SOAP веб-сервис продолжает разрывать соединение

Краткое описание

Я использую JBoss SwitchYard для подключения к защищенному удаленному веб-сервису SOAP. По какой-то причине после отправки запроса; удаленный веб-сервис останавливает дальнейшее общение; поэтому я не получаю ответ.

Вопрос

Мне нужна идея или решение, что может быть проблемой здесь.

ошибка

Вызвано: java.net.SocketException: SocketException, вызывающее https://**********.asmx: неожиданный конец файла с сервера

Описание и примечания

  • Удаленный веб-сервис использует самозаверяющий сертификат; Я импортировал сертификат сервера в локальное хранилище доверенных сертификатов + плюс у меня есть другой сертификат (в хранилище ключей), чтобы идентифицировать себя на удаленном сервере.
  • Благодаря -Djavax.net.debug= всем журналам отладки SSL и журналам Wireshark я знаю, что и клиент, и сервер успешно завершили SSL-квитирование, и клиент успешно отправил запрос.
  • Сервер также использует IP-фильтрацию для прямой связи, и мой IP-адрес находится в белом списке.
  • Если я пытаюсь отправить тот же XML-запрос через SoapUI, он работает нормально, и я получаю ответ. Вы должны принять во внимание, что SoapUI использует только хранилище ключей; он настроен так, чтобы всегда доверять удаленным службам, поэтому хранилище доверенных сертификатов не требуется и не используется.
  • Теперь самое смешное. Если я использую Fiddler (бесплатный прокси-сервер для отладки веб-страниц) в качестве "человека посередине" между моей JBoss SwitchYard и удаленным веб-сервисом (чтобы увидеть, что происходит), внезапно все работает.
  • Единственное отличие между прямым подключением и использованием Fiddler в качестве прокси-сервера заключается в том, что в реальном соединении используется параметр заголовка Connection = Keep-Alive, а в случае Fiddler - параметр Proxy-Connection = Keep-Alive. Я не знаю, есть ли другая существенная разница.
  • Если я вручную изменю эти параметры заголовка в SoapUI, я все равно получу успешный ответ. Соединение не будет установлено, только если мне не хватает параметров заголовка SOAPAction и Content-Type, но они присутствуют в каждом случае (и они одинаковы).
  • Когда я наблюдаю эту связь через Wireshark, я вижу только одно отличие: удаленный сервер останавливает дальнейшую связь (когда приложение JBoss Switchyard напрямую связывается с удаленным веб-сервисом).
  • У меня нет доступа к удаленным журналам, и мне не разрешено их получать. Так что я работаю вслепую.
  • В каждом случае (с или без Fiddler) я использую прокси компании для доступа к удаленному веб-сервису. Этот прокси не является проблемой, потому что другие приложения SwitchYard работают просто отлично.

инструменты

  • JBoss EAP 6.4
  • JBoss SwitchYard 2.0.1.redhat-621159

2 ответа

исключение

java.net.SocketException: неожиданный конец файла с сервера

Это исключение подразумевает, что сервер уже принял ваше соединение, что означает, что ваше SSL-подтверждение действительно успешно. Но сервер закрыл соединение (сбросом TCP или fin), прежде чем вы сможете получить ответ.

Сброс обычно отправляется в двух случаях:

  • постоянное соединение (поддерживать соединение живым) с превышением конфигурации
  • сервер перезагружен потерял соединение

Обычно постоянное соединение имеет две конфигурации:

Keep-Alive: timeout=15, max=100

timeout означает время в секундах, max означает максимальное количество запросов.

Соединение против прокси

Давайте сравним три разных случая, которые вы описали:

  • SoapUI: успешно;?
  • Прямое соединение: сбой; Connection = Keep-Alive
  • Скрипач: преуспеть; Proxy-Connection = Keep-Alive

В третьем случае, если я вас правильно понял, ваше постоянное соединение между клиентом и прокси и между прокси и сервером неясно.

 client----->Proxy----->server

Предложения

  • попытайтесь получить постоянную конфигурацию соединения сервера из ответа (как здесь), чтобы видеть, превышает ли прямое соединение время или числа ограничения
  • постарайтесь не использовать постоянное соединение: java -Dhttp.keepalive=false

ссылка

Возможно, проблема связана с неверным заголовком или неверным форматом запроса SOAP. Попробуйте выполнить код ниже

1 Вам нужен HeaderHandlerResolver

 public class HeaderHandlerResolver implements HandlerResolver {

        public List<Handler> getHandlerChain(PortInfo portInfo) {
            List<Handler> handlerChain = new ArrayList<Handler>();

            HeaderHandler hh = new HeaderHandler();

            handlerChain.add(hh);

            return handlerChain;
        }
    }

Затем нужно добавить класс HeaderHandler

 public class HeaderHandler implements SOAPHandler<SOAPMessageContext> {

        public boolean handleMessage(SOAPMessageContext smc) {

            Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

            if (outboundProperty.booleanValue()) {

                SOAPMessage message = smc.getMessage();

                try {

                    SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope();

                    SOAPHeader header = envelope.getHeader();
                    header.setPrefix("soapenv");
                    header.setAttribute("xmlns:wsa", "http://www.w3.org/2005/08/addressing");

                    SOAPElement security =
                            header.addChildElement("Security", "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");

                    SOAPElement usernameToken =
                            security.addChildElement("UsernameToken", "wsse");
                    usernameToken.addAttribute(new QName("xmlns:wsu"), "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");

                    SOAPElement username =
                            usernameToken.addChildElement("Username", "wsse");
                    username.addTextNode("USERNAME");

                    SOAPElement password =
                            usernameToken.addChildElement("Password", "wsse");
                    password.setAttribute("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
                    password.addTextNode("PASSWORD");

                    SOAPElement encode =
                            usernameToken.addChildElement("Nonce", "wsse");
                    encode.setAttribute("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
                    encode.addTextNode(generateNonce());

                    Calendar createdTime = new GregorianCalendar(TimeZone.getTimeZone("IST"));
                    Date todayDate = createdTime.getTime();
                    todayDate.setTime(todayDate.getTime()-20000000);

                    SOAPElement created = usernameToken.addChildElement("Created", "wsu");
                    created.addTextNode(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sss'Z'").format(todayDate));

                    SOAPElement action = header.addChildElement("Action", "wsa");
                    //YOUR ACTION URL SHOULD BE in BELOW Text Content
                    action.setTextContent("SET HERE YOUR ACTION URL");

                    message.saveChanges();
                    message.writeTo(System.out);
                    System.out.println("");

                } catch (Exception e) {
                    e.printStackTrace();
                }

            } else {
                try {

                    //This handler does nothing with the response from the Web Service so
                    //we just print out the SOAP message.
                    SOAPMessage message = smc.getMessage();
                    message.writeTo(System.out);
                    System.out.println("");
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }


            return outboundProperty;

        }

        public Set getHeaders() {
            return null;
        }

        public boolean handleFault(SOAPMessageContext context) {
            return true;
        }

        public void close(MessageContext context) {
        }

        private static String generateNonce() throws NoSuchAlgorithmException, NoSuchProviderException, UnsupportedEncodingException {
            String dateTimeString = Long.toString(new Date().getTime());
            byte[] nonceByte = dateTimeString.getBytes();
            return Base64.encodeBase64String(nonceByte);
        }
    }

Теперь, наконец, Ваш главный класс для вызова сервиса SOAP

public class SoapClientClass {

    public static void main(String[] args) {

        ImplService service = new ImplService();
        HeaderHandlerResolver handlerResolver = new HeaderHandlerResolver();
        service.setHandlerResolver(handlerResolver);

        ResponseClass port = service.getPortClass();

        Response response = null;
        try {
            response = port.getServerMehotd("Params");
        } catch (PolicyException_Exception e) {
            e.printStackTrace();
        } catch (ServiceException_Exception e) {
            e.printStackTrace();
        }

        }
    }
}

Кроме того, убедитесь, что ваш сгенерированный код с обновлением файла wsdl и URL-адрес сервера также правильно.

Надеюсь, это решит вашу проблему

Другие вопросы по тегам