2009-03-30 28 views
9

Tôi đang cố gắng phát triển một máy khách dịch vụ web Java độc lập với JAX-WS (Metro) sử dụng WS-Security với Xác thực Mã thông báo Người dùng (Password digest, nonces và dấu thời gian) và xác minh dấu thời gian cùng với WS-Addressing qua SSL.JAX-WS Sử dụng dịch vụ web với WS-Security và WS-Addressing

WSDL mà tôi phải làm việc với không xác định bất kỳ thông tin chính sách bảo mật nào. Tôi đã không thể tìm ra chính xác cách thêm thông tin tiêu đề này (cách chính xác để làm như vậy) khi WSDL không chứa thông tin này. Hầu hết các ví dụ tôi đã tìm thấy bằng cách sử dụng Metro xoay quanh việc sử dụng Netbeans để tự động tạo điều này từ WSDL mà không giúp tôi chút nào. Tôi đã xem xét WSIT, XWSS, vv mà không có nhiều sự rõ ràng hoặc hướng. JBoss WS Metro trông đầy hứa hẹn cũng không có nhiều may mắn.

Bất kỳ ai có kinh nghiệm làm việc này hoặc có đề xuất về cách thực hiện tác vụ này? Ngay cả chỉ cho tôi đi đúng hướng sẽ hữu ích. Tôi không bị hạn chế đối với một công nghệ cụ thể nào khác ngoài công nghệ phải dựa trên Java.

Trả lời

8

Tôi đã kết thúc tìm ra vấn đề này nhưng tôi đã đi theo một hướng khác để làm như vậy. Giải pháp của tôi là sử dụng CXF 2.1 và triển khai JAX-WS, kết hợp sức mạnh của CXF với cơ sở hạ tầng Spring hiện có mà tôi đã có sẵn. Tôi đã hoài nghi lúc đầu vì rất nhiều lọ được yêu cầu bởi CXF, nhưng cuối cùng nó cung cấp giải pháp tốt nhất và đơn giản nhất.

Áp dụng ví dụ từ CXF website for client configuration, tôi đã sử dụng không gian tên CXAX JAXWS tùy chỉnh trong mùa xuân và sử dụng Trình chặn bên ngoài cho Xác thực mã thông báo tên người dùng (Xác thực mật khẩu, nonces và dấu thời gian) và xác minh dấu thời gian. Bước duy nhất khác để thực hiện công việc này là tạo trình xử lý gọi lại mật khẩu của riêng tôi được thực thi cho mỗi yêu cầu SOAP gửi đi.

Đối với cấu hình SSL, tôi lại chuyển sang CXF and its SSL support via conduits, mặc dù tôi không bao giờ làm cho SSL hoạt động với tên http: conduit cụ thể, tôi phải sử dụng mục đích chung không được khuyến nghị cho môi trường sản xuất.

Dưới đây là ví dụ về tệp cấu hình của tôi.

tập mùa xuân cấu hình

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:jaxws="http://cxf.apache.org/jaxws" 
    xmlns:sec="http://cxf.apache.org/configuration/security" 
    xmlns:http="http://cxf.apache.org/transports/http/configuration" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:cxf="http://cxf.apache.org/core" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
    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://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd 
    http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd 
    http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd"> 

    <context:property-placeholder location="meta/my.properties" /> 
    <context:component-scan base-package="com.foo" /> 

    <import resource="remoting.xml" /> 
    <jaxws:client id="myWebService" address="${my.endpointAddress}" 
        serviceClass="com.foo.my.ServicePortType"> 

<!-- Testing only, adds logging of entire message in and out --> 
<jaxws:outInterceptors> 
    <ref bean="TimestampUsernameToken_Request" /> 
    <ref bean="logOutbound" /> 
</jaxws:outInterceptors> 
<jaxws:inInterceptors> 
     <ref bean="logInbound" /> 
    </jaxws:inInterceptors> 
    <jaxws:inFaultInterceptors> 
     <ref bean="logOutbound" /> 
    </jaxws:inFaultInterceptors> 

<!-- Production settings --> 
<!-- 
    <jaxws:outInterceptors> <ref bean="TimestampUsernameToken_Request" /> 
    </jaxws:outInterceptors> 
    --> 
</jaxws:client > 



<!-- 
    CXF Interceptors for Inbound and Outbound messages 
    Used for logging and adding Username token/Timestamp Security Header to SOAP message 
--> 
<bean id="logInbound" class="org.apache.cxf.interceptor.LoggingInInterceptor" /> 
<bean id="logOutbound" class="org.apache.cxf.interceptor.LoggingOutInterceptor" /> 

<bean id="TimestampUsernameToken_Request" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor"> 
    <constructor-arg> 
     <map> 
      <entry key="action" value="UsernameToken Timestamp" /> 
      <entry key="user" value="${my.group}.${my.userId}" /> 
      <entry key="passwordType" value="PasswordDigest" /> 
      <entry key="passwordCallbackClass" value="com.foo.my.ClientPasswordHandler" /> 
     </map> 
    </constructor-arg> 
</bean> 

<!-- 
    http:conduit namespace is used to configure SSL using keystores, etc 
    *.http-conduit works but CXF says its only supposed to be for temporary use (not production), 
    well until the correct way works, we're going to use it. 
--> 
<http:conduit name="*.http-conduit"> 
    <http:tlsClientParameters 
        secureSocketProtocol="SSL"> 
        <!-- 
      <sec:trustManagers> 
     <sec:keyStore type="JKS" 
         password="${my.truststore.password}" 
         file="${my.truststore.file}" /> 
        </sec:trustManagers> 
        --> 
        <sec:keyManagers keyPassword="${my.keystore.password}"> 
        <sec:keyStore type="JKS" 
         password="${my.keystore.password}" 
         file="${my.keystore.file}" /> 
        </sec:keyManagers> 

        <!-- Cipher suites filters specify the cipher suite to allow/disallow in SSL communcation --> 
        <sec:cipherSuitesFilter> 
        <sec:include>.*_WITH_3DES_.*</sec:include> 
        <sec:include>.*_EXPORT_.*</sec:include> 
        <sec:include>.*_EXPORT1024_.*</sec:include 
        <sec:include>.*_WITH_DES_.*</sec:include 
        <sec:exclude>.*_WITH_NULL_.*</sec:exclude 
        <sec:exclude>.*_DH_anon_.*</sec:exclude> 
        </sec:cipherSuitesFilter> 
    </http:tlsClientParameters> 
</http:conduit> 
</beans> 

Java Khách hàng Mật khẩu Handler:

import java.io.IOException; 

import javax.security.auth.callback.Callback; 
import javax.security.auth.callback.CallbackHandler; 
import javax.security.auth.callback.UnsupportedCallbackException; 

import org.apache.log4j.Logger; 
import org.apache.ws.security.WSPasswordCallback; 


/** 
* <p> 
* Provides a callback handler for use processing outbound/inbound SOAP messages. 
* ClientPasswordHandler sets the password used in the WS-Security UsernameToken 
* SOAP header. 
* 
* </p> 
* 
* Created: Apr 1, 2009 
* @author Jared Knipp 
* 
*/ 
public final class ClientPasswordHandler implements CallbackHandler { 
    protected static Logger log = Logger.getLogger(ClientPasswordHandler.class); 

    private static final PropertyManager PROPS = PropertyManager.getInstance(); 
    private static String PASSWORD = PROPS.getPassword(); 
    private static boolean IS_PASSWORD_CLEAR = PROPS.getIsClearPassword(); 

    /** 
    * Client password handler call back. This method is used to provide 
    * additional outbound (or could be inbound also) message processing. 
    * 
    * Here the method sets the password used in the UsernameToken SOAP security header 
    * element in the SOAP header of the outbound message. For our purposes the clear 
    * text password is SHA1 hashed first before it is hashed again along with the nonce and 
    * current timestamp in the security header. 
    */ 
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { 
     if(log.isDebugEnabled()) { log.debug("Setting password for UsernameToken"); } 
     WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]; 


     // Check to see if the password is already Hashed via SHA1, if not then hash it first 
     if(IS_PASSWORD_CLEAR) { 
      synchronized(this) { 
       PASSWORD = PasswordDigestUtil.doPasswordDigest(PASSWORD); 
       IS_PASSWORD_CLEAR = false; 
       PROPS.setIsClearPassword(IS_PASSWORD_CLEAR); 
       PROPS.setPassword(PASSWORD); 
       PROPS.saveProperties(); 
      } 
     } 

     pc.setPassword(PASSWORD); 
    } 
} 
0

Nếu thông tin không có trong WSDL, bạn có chắc chắn rằng nó nằm trong dịch vụ được mô tả bởi WSDL không? WSDL có nghĩa là cung cấp tất cả thông tin cần thiết để mô tả dịch vụ, bao gồm các chính sách bảo mật cần thiết để sử dụng dịch vụ.

WSDL nền tảng nào đến từ đâu? Có thể WSDL không phải là mô tả đầy đủ không? Ví dụ: có thể là WSDL là bao gồm d trong một WSDL khác mà làm cung cấp thông tin bảo mật.

+0

Hãy để tôi làm rõ, nó không có trong WSDL mà tôi đã được cấp quyền truy cập. Các tài liệu tôi có lỗ (không đề cập đến dấu thời gian) để exlusion thông tin WSDL sẽ không làm tôi ngạc nhiên. –

+0

Vâng, bạn sẽ cần WSDL thực sự để gọi dịch vụ thực sự.Đó là tất cả về nó. –

+0

Vì vậy, không có khả năng rằng WSDL lá này ra nhưng nó được thực hiện trên máy chủ? Máy chủ là Java (có thể là JBoss hoặc Websphere) sử dụng một số phiên bản của Axis. –

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