2011-09-01 40 views
9

Trước tiên, tôi sẽ bắt đầu với một bản tóm tắt. Tôi đang sử dụng ứng dụng khách Apache CXF để giao tiếp qua SSL với nhà cung cấp dịch vụ Apache CXF đang sử dụng chứng chỉ tự ký. Tôi đã nhập chứng chỉ vào kho ủy nhiệm WebSphere trên máy chủ khách, nhưng tôi vẫn nhận được một "javax.net.ssl.SSLHandshakeException: SSLHandshakeException gọi https://somesvcprovider.com/appname/svc/myservice: com.ibm.jsse2.util.h: Không có chứng chỉ đáng tin cậy nào được tìm thấy" ngoại lệ.Cách thiết lập ứng dụng khách Apache CXF để sử dụng WebSphere truststore? (Nhận được "Không tìm thấy chứng chỉ đáng tin cậy" ngoại lệ.)

Bây giờ, đây là chi tiết:

Tôi có một khách hàng dịch vụ web Apache CXF mà tôi đang cấu hình sử dụng Spring, và khách hàng được triển khai tới một máy chủ ứng dụng WebSphere 6.1. Máy khách CXF liên lạc với nhà cung cấp dịch vụ Apache CXF trên một máy chủ WebSphere khác. Giao tiếp sử dụng SSL.

Nhà cung cấp dịch vụ đang sử dụng chứng chỉ tự ký. Tôi đã nhập chứng chỉ của nhà cung cấp vào kho ủy thác WebSphere trên máy chủ khách thông qua bảng điều khiển quản trị. Tôi đã thực hiện việc này bằng cách chuyển tới chứng chỉ SSL và quản lý khóa> Cấu hình SSL> NodeDefaultSSLSettings> Cửa hàng và chứng chỉ> NodeDefaultTrustStore> Chứng chỉ người ký; sau đó tôi sử dụng công cụ "Lấy từ cổng" để nhập chứng chỉ.

Tuy nhiên, tôi vẫn nhận được lỗi này khi cố gắng liên hệ với nhà cung cấp dịch vụ: "javax.net.ssl.SSLHandshakeException: SSLHandshakeException gọi https://somesvcprovider.com/appname/svc/myservice: com.ibm.jsse2.util.h: Không tìm thấy chứng chỉ đáng tin cậy".

Các tập tin cấu hình Spring như sau:

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:sec="http://cxf.apache.org/configuration/security" 
    xmlns:http="http://cxf.apache.org/transports/http/configuration" 
    xmlns:jaxws="http://cxf.apache.org/jaxws" 
    xsi:schemaLocation=" 
     http://cxf.apache.org/configuration/security 
     http://cxf.apache.org/schemas/configuration/security.xsd 
     http://cxf.apache.org/transports/http/configuration 
     http://cxf.apache.org/schemas/configuration/http-conf.xsd 
     http://cxf.apache.org/jaxws 
     http://cxf.apache.org/schemas/jaxws.xsd 
     http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans.xsd"> 
    <http:conduit name="*.http-conduit"> 
     <!-- deactivate HTTPS url hostname verification (localhost, etc) --> 
     <!-- WARNING ! disableCNcheck=true should not used in production. --> 
     <http:tlsClientParameters disableCNCheck="true" /> 
    </http:conduit> 
    <!-- Read properties from property file(s). --> 
    <bean id="propertyPlaceholderConfigurer" 
      class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
     <property name="locations"> 
      <list> 
       <!-- The *.spring.properties files are prefixed with a system property 
        that is set on the WebSphere server. --> 
       <value>classpath:spring.${my.env}.properties</value> 
      </list> 
     </property> 
    </bean> 
    <jaxws:client id="myServiceClient" 
     serviceClass="com.client.stub.cxf.IMyService" 
     address="${my.svc.url}" /> 
    <bean id="myReport" class="com.client.MyReportRequestor"> 
     <property name="client" ref="myServiceClient"/> 
    </bean> 
</beans> 

Như đã trình bày ở trên, khách hàng CXF được tiêm qua một setter bởi Spring. Các mã để liên lạc với dịch vụ là bên dưới:

List<String> formNames = client.retrieveNames(formIdsList); 

Ngoài ra, tôi không biết nếu điều này có liên quan, nhưng không có nhà quản lý tin tưởng được trả về khi tôi kiểm tra việc TLSClientParameters đối tượng trên máy khách CXF khi chạy. Mã để thực hiện việc kiểm tra dưới đây:

// Get the trust managers for this client. 
Client proxy = ClientProxy.getClient(client); 
HTTPConduit conduit = (HTTPConduit) proxy.getConduit(); 
TLSClientParameters tls = conduit.getTlsClientParameters(); 
TrustManager[] trustManagers = tls.getTrustManagers(); // trustManagers is null 

Có điều gì khác mà tôi cần làm để yêu cầu khách hàng Apache CXF tin tưởng chứng chỉ tự ký không?

Tôi không muốn chỉ định đường dẫn đến một truststore cùng với mật khẩu trong tệp cấu hình.

Cảm ơn bạn!

Trả lời

0

Tôi không nghĩ rằng bạn có thể sử dụng các keystore của WAS giống như vậy với thành phần bên ngoài (Apache CXF). Bạn có thể phải xây dựng và sử dụng your own TrustManager. Dường như có một số làm việc examples xung quanh cho điều đó.

+0

Tôi không thể tìm cách sử dụng WAS truststores, vì vậy, tôi sẽ giả định rằng bạn phải chỉ định truststore trong tệp cấu hình như bạn đã đề cập. –

+0

Tôi tìm giải pháp @kjetil khả thi hơn, vì nó không yêu cầu phát triển tùy chỉnh –

2

Nhìn CXF và WS hoạt động như thế nào, việc truy cập vào SSLSocketFactory của Websphere và chuyển nó sang CXF bằng cách sử dụng bộ chặn đánh chặn ra ngoài là khá đơn giản.

Nếu bạn sử dụng các lớp sau:

public class WebsphereSslOutInterceptor extends AbstractPhaseInterceptor<Message> { 

    private String sslAlias = null; 

    public WebsphereSslOutInterceptor() { 
    super(Phase.SETUP); 
    } 

    public void handleMessage(Message message) throws Fault { 
    Conduit conduit = message.getExchange().getConduit(message); 
    if (conduit instanceof HTTPConduit) { 
     HTTPConduit httpConduit = (HTTPConduit)conduit; 
     String endpoint = (String) message.get(Message.ENDPOINT_ADDRESS); 
     if (endpoint != null) { 
     try { 
      URL endpointUrl = new URL(endpoint); 
      Map<String, String> connectionInfo = new HashMap<String, String>(); 

      connectionInfo.put(
      JSSEHelper.CONNECTION_INFO_REMOTE_HOST, 
      endpointUrl.getHost()); 
      connectionInfo.put(
      JSSEHelper.CONNECTION_INFO_REMOTE_PORT, 
      Integer.toString(endpointUrl.getPort())); 
      connectionInfo.put(
      JSSEHelper.CONNECTION_INFO_DIRECTION, 
      JSSEHelper.DIRECTION_OUTBOUND); 
      SSLSocketFactory factory = 
      JSSEHelper.getInstance().getSSLSocketFactory(
       sslAlias, 
       connectionInfo, 
       null); 

      TLSClientParameters tlsClientParameters = httpConduit.getTlsClientParameters(); 
      if (tlsClientParameters != null) { 
      tlsClientParameters.setSSLSocketFactory(factory); 
      } 
     } catch (MalformedURLException e) { 
      throw new Fault(e); 
     } catch (SSLException e) { 
      throw new Fault(e); 
     } 
     } 
    } 
    } 

    public void setSslAlias(String sslAlias) { 
    this.sslAlias = sslAlias; 
    } 
} 

Sau đó, bạn sẽ có thể treo lên để SSLSocketFactory Websphere và có thể tùy chọn sử dụng "Dynamic Outbound Endpoint SSL Cấu hình" Cài đặt để xác định bất kỳ Certs khách hàng, bằng cách xác định đánh chặn trong thẻ jaxws:client:

<jaxws:client id="proxyName" 
     serviceClass="proxyClass" 
     address="${web.service.endpointaddress}"> 

    <jaxws:outInterceptors> 
     <bean class="my.pkg.WebsphereSslOutInterceptor" /> 
    </jaxws:outInterceptors> 
</jaxws:client> 

là một sang một bên, nếu tài sản sslAlias được khai báo trong WebsphereSslOutInterceptor, một giấy chứng nhận khách hàng có thể được lựa chọn dựa trên bí danh của nó.

Vì đây là sử dụng SSLSocketFactory từ Websphere, các cửa hàng tin cậy cũng sẽ được sử dụng từ Websphere.

EDIT:

tôi đã sử dụng CXF 2.3.6 và Websphere 6.1

+0

Giải pháp này làm việc cho tôi miễn là tôi giữ định nghĩa chặn trong cấu hình điểm cuối. Tuy nhiên, nếu tôi đặt nó trên xe buýt, phương thức handleMessage không được gọi. Có ai biết tại sao không? Tôi không muốn chỉ định cùng một trình chặn cho mỗi điểm cuối. – Sandman

+0

@ beny23 Nếu tôi đang sử dụng Điểm cuối động của Websphere, tôi có cần tất cả các công cụ đánh chặn và SSLSocketFactory không? Sự hiểu biết của tôi là tôi có thể thực hiện cuộc gọi SSL đơn giản từ mã của tôi và Điểm cuối động sẽ chặn tất cả các yêu cầu gửi đi dựa trên kết hợp URL. Đúng không? – CodeClimber

7

CXF có lẽ sử dụng nhà máy ổ cắm SSL sai.

Hãy thử thêm này để cấu hình mùa xuân của bạn: giải pháp

<http-conf:conduit name="*.http-conduit"> 
    <http-conf:tlsClientParameters useHttpsURLConnectionDefaultSslSocketFactory="true"/> 
</http-conf:conduit> 
+0

Cảm ơn, điều này phù hợp với tôi! - [WAS 8] [CXF 2.7.18] – DaniEll

+0

Làm việc cho tôi quá ... ngay cả khi sử dụng ProxyFactoryBean để tạo ứng dụng khách [din 8.5ically] [CXF 3.1.8] –

2

beny23 của hoạt động tuyệt vời đối với tôi trên WAS7, với những sửa đổi sau (lý do: httpConduit.getTlsClientParameters() có thể là null):

Thay thế phần này:

TLSClientParameters tlsClientParameters = httpConduit.getTlsClientParameters(); 
    if (tlsClientParameters != null) { 
     tlsClientParameters.setSSLSocketFactory(factory); 
    } 

Với điều này:

TLSClientParameters tlsClientParameters = httpConduit.getTlsClientParameters(); 
    if (tlsClientParameters == null) { 
     tlsClientParameters = new TLSClientParameters(); 
     httpConduit.setTlsClientParameters(tlsClientParameters); 
    } 
    tlsClientParameters.setSSLSocketFactory(factory); 
Các vấn đề liên quan