2012-01-28 88 views
6

我必须使用相互身份验证从java调用安全的WCF服务。 一切工作正常,但我无法发送大于48680字节大小的消息。因此成功发送了48680字节的消息,但是48681字节不是,并且java应用程序失败,读取超时异常,尽管WCF的配额设置允许更大的消息。无法发送48681字节的消息来保护来自java的wcf服务

那么会有什么问题呢?


编辑

的源代码:

package foo.bar; 

import org.apache.commons.io.FileUtils; 
import org.apache.commons.io.IOUtils; 
import org.junit.Test; 

import javax.net.ssl.*; 
import java.io.*; 
import java.net.URL; 
import java.security.KeyStore; 

public class ReadTimedOutTest { 

    @Test 
    public void testReadTimedOut() throws Exception { 
     URL url = new URL("https://services/endpoint/"); 

     HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); 
     setUpSSL(connection); 
     connection.setDoOutput(true); 
     connection.setDoInput(true); 
     connection.setRequestMethod("POST"); 
     connection.setRequestProperty("SOAPAction", "http://namespace/2012/01/service/Operation"); 
     connection.setRequestProperty("Accept", "*/*"); 
     connection.setRequestProperty("Connection", "Keep-Alive"); 
     connection.setRequestProperty("Content-Type", "text/xml; charset=utf-8"); 

     connection.setConnectTimeout(10 * 1000); 
     connection.setReadTimeout(10 * 1000); 
     connection.setInstanceFollowRedirects(true); 

     ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
     InputStream is = ReadTimedOutTest.class.getResourceAsStream("payload.failure.xml"); 
     try { 
      IOUtils.copy(is, bos); 
     } finally { 
      is.close(); 
     } 
     byte[] bytes = bos.toByteArray(); 
     connection.setRequestProperty("Content-Length", String.valueOf(bytes.length)); 

     OutputStream os = connection.getOutputStream(); 
     try { 
      IOUtils.copy(new ByteArrayInputStream(bytes), os); 
      os.flush(); 
     } finally { 
      os.close(); 
     } 

     int respCode = connection.getResponseCode(); 
     if(respCode >= HttpsURLConnection.HTTP_INTERNAL_ERROR) { 
      is = connection.getErrorStream(); 
      try { 
       IOUtils.copy(is, System.err); 
      } finally { 
       is.close(); 
      } 
     } else { 
      is = connection.getInputStream(); 
      try { 
       IOUtils.copy(is, System.out); 
      } finally { 
       is.close(); 
      } 
     } 
    } 

    private void setUpSSL(HttpsURLConnection connection) throws Exception { 
     byte[] bytes = FileUtils.readFileToByteArray(new File("d:\\workspace\\temp\\keystore")); 
     KeyStore keyStore = KeyStore.getInstance("JKS"); 
     keyStore.load(new ByteArrayInputStream(bytes), "changeit".toCharArray()); 
     KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509"); 
     keyManagerFactory.init(keyStore, "changeit".toCharArray()); 

     bytes = FileUtils.readFileToByteArray(new File("d:\\workspace\\temp\\truststore")); 
     KeyStore trustStore = KeyStore.getInstance("JKS"); 
     trustStore.load(new ByteArrayInputStream(bytes), "changeit".toCharArray()); 
     TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509"); 
     trustManagerFactory.init(trustStore); 

     SSLContext context = SSLContext.getInstance("TLS"); 
     context.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); 
     SSLSocketFactory socketFactory = context.getSocketFactory(); 

     connection.setSSLSocketFactory(socketFactory); 
    } 

} 

UPDATE

我与.NET WCF客户端测试用的服务,它是能调用服务器冰成功,所以我想知道可能是什么问题?为什么WCF客户端能够调用服务和Java客户端,即使使用普通的HTTP POST请求UrlConnection,是不是?


UPDATE

这里是SOAP消息的样品

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soap:Body> 
     <DoSomethingUseful xmlns="http://namespace/2012/01/service"> 
     ... 
     </DoSomethingUseful> 
    </soap:Body> 
</soap:Envelope> 

UPDATE

有人告诉我,在.NET服务端有"Client certificate is required. No certificate was found in the request"似乎在ssl会话恢复时发生的消息。只有当内容长度大于48680字节时才会发生。 也使用basicHttpBinding配置WCF服务以使用传输级别安全性。

+0

您能否提供您的WCF服务配置? – 2012-01-28 15:57:13

+0

不幸的是,这是我工作的组织使用的外部服务。可能我会在星期一之前获得配置。 只有当我试图发送足够大的请求时才会出现此问题。当收到大的回应时,没有任何问题。 WCF服务的开发人员表示,从其内部网络使用.net客户端调用此服务时没有任何问题。 – szhem 2012-01-28 16:18:29

+0

他们是否从他们的内部网络使用与您相同的端点? – 2012-01-28 16:29:29

回答

1

你试过看看发送的实际数据包 - 例如:与tcpdump/Wireshark(http://www.wireshark.org/)?

我曾经在某些平台上遇到过问题,这些平台到达了一个非常挑剔的SSL卸载引擎后面的服务。

+0

我有。不幸的是,从Java方面来说,没有什么特别的。下面是交互的样子:1.从java客户端到.net服务的_ack push_; 2.阅读超时; 3.将fin_ packet从java客户端发送到.net服务; 4.net服务的回复是_ack_ – szhem 2012-02-07 08:42:38

+0

.net客户端由服务的开发者提供,所以我必须要求他们修改一下。我会尽快让你知道结果。 – szhem 2012-02-08 23:04:55

+0

嗨,@anders。我已经发布了这个问题的答案。问题在于重新谈判。 – szhem 2012-02-10 08:36:16

0

你问,什么可能是问题,这里有些建议:

  • 您请求的大小。这基本上是你的假设,如果我理解正确的话。
  • 您的请求的结构。
  • 服务器端策略,如请求必须小于48681字节。在评论中,您告诉我们您正在使用外部服务器,但不受您的控制
  • 服务器端错误。记住不在你的控制下部分并将其读为buggy
  • 比赛条件。

我建议尝试更广泛的请求。不仅要改变大小。

+0

- 问题肯定不在配额中,因为.net客户端能够发送更大的请求 - 我不认为请求的结构是一个问题,因为它来自.net客户端的跟踪 - 本主题前面提到的服务器端策略允许更大的请求 – szhem 2012-02-06 23:07:57

0

您是否尝试过使用SOAPUI工具发送请求并检查其行为是否相同。另外值得关注的是下面的链接,讨论关于WCF服务和Java客户端的一些内容。

Java Client and WCF Service

0

这可能是一个SOAP版本不匹配。 basichttpbinding的默认版本是SOAP 1.1。如果Java客户端使用SOAP 1.2,则会出现错误。

我们经常看到,当SOAP版本不匹配时得到的错误与真正的错误无关。

+0

Java使用soap 1.1。很抱歉,这不是清晰可见,但示例中的soap命名空间是* http \://schemas.xmlsoap.org/soap/envelope/*,content-type是* text/xml *。 – szhem 2012-02-07 20:20:46

0

最后,我解决了这个问题。 问题是以下几点:给定的.NET客户端的

  1. 加密服务提供程序支持TLS重新协商
  2. 加密的Java的客户端的供应商不支持TLS重新协商
  3. 对服务的有侧没有ClientCertNegotiation选项设置,所以Java客户端无法重新协商。
  4. .net服务未响应正在等待数据的java客户端,因为此服务需要客户端证书,但客户端无法提供它,因为不支持重新协商。
+0

很高兴听到你解决它。 – 2012-02-10 08:45:02