2012-01-28 25 views
6

Tôi phải gọi dịch vụ WCF an toàn từ java bằng cách sử dụng xác thực lẫn nhau. Mọi thứ hoạt động tốt trừ khi tôi không thể gửi tin nhắn có kích thước lớn hơn 48680 byte. Vì vậy, 48680 byte tin nhắn được gửi thành công, nhưng 48681 byte - không, và ứng dụng java không thành công với ngoại lệ đọc hết thời gian, mặc dù thiết lập hạn ngạch của WCF cho phép các thông điệp lớn hơn nhiều.Không thể gửi thư 48681 byte để bảo mật dịch vụ wcf từ java

Vì vậy, vấn đề có thể là gì?


EDIT

Mã nguồn:

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); 
    } 

} 

CẬP NHẬT

Tôi đã thử nghiệm dịch vụ với khách hàng WCF .net và nó đã có thể gọi serv băng thành công, vì vậy tôi tự hỏi điều gì có thể là vấn đề? Tại sao WCF khách hàng có thể gọi dịch vụ và máy khách Java, ngay cả khi sử dụng yêu cầu HTTP POST thông thường với UrlConnection, phải không?


CẬP NHẬT

Dưới đây là mẫu thông điệp xà phòng

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

CẬP NHẬT

tôi được cho biết rằng ở phía bên dịch vụ .net có "Client certificate is required. No certificate was found in the request" các thông báo dường như xảy ra khi nối lại phiên ssl. Nó chỉ xảy ra khi Content-Length lớn hơn 48680 bytes. Dịch vụ WCF cũng được cấu hình với basicHttpBinding để sử dụng bảo mật mức truyền tải.

+0

Bạn có thể cung cấp cấu hình dịch vụ WCF của mình không? –

+0

Thật không may đây là dịch vụ bên ngoài được sử dụng bởi tổ chức mà tôi đang làm việc. Có lẽ tôi sẽ có được cấu hình vào thứ hai. Sự cố chỉ xảy ra khi tôi đang cố gửi yêu cầu đủ lớn. Khi nhận được phản hồi lớn, không có vấn đề gì. Nhà phát triển dịch vụ WCF nói rằng không có bất kỳ vấn đề nào khi gọi dịch vụ này bằng ứng dụng khách .net từ mạng nội bộ của họ. – szhem

+0

Có phải họ đang sử dụng cùng điểm cuối với bạn từ mạng nội bộ của họ không? –

Trả lời

1

Bạn đã thử xem các gói thực đang được gửi - ví dụ: với tcpdump/Wireshark (http://www.wireshark.org/)?

Tôi đã từng gặp sự cố chỉ trên một số nền tảng nhất định tiếp cận một dịch vụ nằm phía sau một công cụ tải SSL SSL rất cầu kỳ.

+0

Tôi có. Thật không may từ phía java không có gì đặc biệt. Đây là cách tương tác trông như thế nào: 1. một _ack push_ từ máy khách java sang dịch vụ .net; 2. đọc thời gian ra; 3. _bất gói fin_ từ máy khách java vào dịch vụ .net; 4. .net dịch vụ trả lời với _ack_ – szhem

+0

. Net khách hàng được cung cấp bởi các nhà phát triển của dịch vụ, vì vậy tôi phải yêu cầu họ sửa đổi nó một chút. Tôi sẽ cho bạn biết về kết quả sớm. – szhem

+0

Xin chào, @anders. Tôi đã đăng câu trả lời cho câu hỏi này. Vấn đề là trong việc đàm phán lại tls. – szhem

0

Bạn hỏi, những gì thể thể là vấn đề, ở đây một số gợi ý:

  • kích thước yêu cầu của bạn. Đó là cơ bản bạn giả định, nếu tôi hiểu nó đúng.
  • cấu trúc yêu cầu của bạn.
  • chính sách phía máy chủ, như yêu cầu phải nhỏ hơn 48681 byte. Trong nhận xét, bạn cho chúng tôi biết rằng bạn đang sử dụng máy chủ bên ngoài, không thuộc quyền kiểm soát của bạn
  • lỗi máy chủ. Hãy nhớ rằng không nằm trong tầm kiểm soát của bạn và đọc nó là lỗi.
  • điều kiện chủng tộc.

Tôi khuyên bạn nên thử nhiều yêu cầu hơn. Không chỉ thay đổi kích thước.

+0

- Vấn đề chắc chắn không nằm trong hạn ngạch, vì .net client có thể gửi các yêu cầu lớn hơn - Tôi không nghĩ cấu trúc của yêu cầu là một vấn đề, vì nó được lấy từ dấu vết của máy khách .net - Chính sách phía máy chủ như tôi đã đề cập trước đó trong chủ đề cho phép yêu cầu lớn hơn nhiều – szhem

0

Bạn đã thử gửi yêu cầu từ công cụ SOAPUI và kiểm tra xem nó có hoạt động giống nhau không. Cũng đáng xem xét các liên kết dưới đây thảo luận về một cái gì đó về WCF Dịch vụ và khách hàng Java.

Java Client and WCF Service

0

Đây có thể là một phiên bản SOAP không phù hợp. Phiên bản mặc định cho basichttpbinding là SOAP 1.1. Nếu máy khách java đang sử dụng SOAP 1.2, bạn sẽ gặp lỗi.

Chúng tôi thường thấy rằng lỗi bạn nhận được khi phiên bản SOAP không khớp, không có gì liên quan đến erros thực.

+0

Java sử dụng xà phòng 1.1. Xin lỗi rằng điều này không hiển thị rõ ràng, nhưng không gian tên xà phòng trong các mẫu là * http \: //schemas.xmlsoap.org/soap/envelope/*, loại nội dung là * text/xml *. – szhem

0

Cuối cùng, tôi đã giải quyết được vấn đề. Vấn đề là như sau:

  1. cung cấp dịch vụ mật mã của khách hàng .net được hỗ trợ tls đàm phán lại
  2. cung cấp mật mã của java-client không hỗ trợ TLS đàm phán lại
  3. ở mặt bên của dịch vụ đã có không có thiết lập tùy chọn ClientCertNegotiation, vì vậy ứng dụng khách java không thể thương lượng lại được.
  4. . Dịch vụ mạng không phản hồi ứng dụng khách java đang đợi dữ liệu, vì dịch vụ này dự kiến ​​chứng chỉ ứng dụng khách, nhưng khách hàng không thể cung cấp, vì việc thương lượng lại không được hỗ trợ.
+0

Rất vui được nghe bạn giải quyết nó. –

Các vấn đề liên quan