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

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

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

Вопрос

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

Error

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

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

  • Удаленный веб-сервис использует самозаверяющий сертификат; Я импортировал сертификат сервера в свою локальную доверенность + плюс у меня есть мой другой сертификат (в моем хранилище ключей), чтобы идентифицировать себя на удаленном сервере.
  • Благодаря -Djavax.net.debug = all журналам отладки 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

Ответы

Ответ 1

Exception

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

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

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

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

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

Keep-Alive: timeout=15, max=100

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

Соединение с прокси-соединением

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

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

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

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

Предложения

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

Ссылка

Ответ 2

Проблема может быть вызвана недопустимым заголовком или недопустимым форматом запроса 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 uptodate и URL-адрес расположения сервера также исправлены.

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