远程SOAP Web服务不断断开连接

时间:2017-05-15 08:35:26

标签: java web-services fiddler jboss-eap-6 switchyard

简短说明

我使用 JBoss SwitchYard 连接到安全的远程SOAP Web服务。发出请求后出于某种原因;远程Web服务正在停止任何进一步的通信;所以我没有收到回复。

问题

我需要一个想法或解决方案,这可能是一个问题。

错误

  

引起:java.net.SocketException:调用https://**********.asmx的SocketException:来自服务器的文件意外结束

描述和注释

  • 远程Web服务使用自签名证书;我已将服务器证书导入到我的本地信任库+我已获得其他证书(在我的密钥库中)以向远程服务器标识自己。
  • 感谢 -Djavax.net.debug = all SSL调试日志和 Wireshark 日志,我知道客户端和服务器都成功进行了SSL握手,客户端已成功发送请求。
  • 服务器还使用IP过滤来进行直接通信,并将我的IP列入白名单。
  • 如果我尝试通过 SoapUI 发送相同的XML请求,它的工作正常,我会收到回复。您应该考虑 SoapUI 仅使用密钥库;它被设置为始终信任远程服务,因此不需要或使用信任库。
  • 现在来了有趣的部分。如果我使用 Fiddler (免费的网络调试代理)作为“中间人”#34;在我的 JBoss SwitchYard 和远程Web服务之间(看看发生了什么),突然一切正常。
  • 直接连接与使用 Fiddler 作为代理之间的唯一区别在于,在实际连接中使用 Connection = Keep-Alive 标头参数,在Fiddler情况下,使用Proxy-Connection = Keep-Alive 参数。我不知道还有其他重大差异。
  • 如果我在 SoapUI 中手动更改这些标头参数,我仍会收到成功的回复。只有当我缺少 SOAPAction Content-Type 标头参数时,连接才会失败,但它们在每种情况下都存在(并且相同)。
  • 当我通过 Wireshark 观察此通信时,我可以看到远程服务器正在停止进一步的通信(当 JBoss Switchyard 应用程序直接与远程Web服务通信时)
  • 我无法访问远程日志,也无法获取远程日志。所以我在盲目工作。
  • 在每种情况下(有或没有Fiddler)我都使用公司代理来访问远程Web服务。这个代理不是问题,因为其他SwitchYard应用程序工作正常。

工具

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

2 个答案:

答案 0 :(得分:5)

异常

  

java.net.SocketException:来自服务器的文件意外结束

此异常表示服务器已接受您的连接,这意味着您的SSL握手确实成功。但是,在获得响应之前,服务器关闭了连接(通过TCP重置或fin)。

通常会在两种情况下发送重置:

  • 配置超过
  • 的持久连接(保持活动连接)
  • 服务器重启失去了连接

通常,持久连接有两个配置:

Keep-Alive: timeout=15, max=100

timeout表示以秒为单位的时间,max表示最多请求。

连接与代理连接

让我们比较您描述的三种不同情况:

  • SoapUI:成功; ?
  • 直接连接:失败; Connection = Keep-Alive
  • Fiddler:成功;代理连接=保持活跃

在第三种情况下,如果我理解你正确,你的持久连接是从客户端到代理,从代理到服务器的连接不清楚。

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

建议

  • 尝试从响应中获取服务器的持久连接配置(如here),以查看直接连接是否超过时间或限制数量
  • 尝试不使用持久连接:java -Dhttp.keepalive=false

参考

答案 1 :(得分:0)

问题可能是由于无效的标头或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 file uptodate和服务器位置URL也是正确的。

希望它能解决你的问题