2009-03-30 27 views
9

WS-SecurityとUsername Token Authenticationを使用するJAX-WS(Metro)を使用してスタンドアロンJava Webサービスクライアントを開発しようとしています(パスワードダイジェスト、noncesおよびタイムスタンプ)とタイムスタンプ検証とSSL上のWS-Addressingを使用します。WS-SecurityとWS-Addressingを使用したWebサービスの使用

私が扱っているWSDLは、セキュリティポリシー情報を定義していません。 WSDLにこの情報が含まれていない場合、このヘッダー情報を追加する方法(正しい方法)を正確に把握することができませんでした。私がMetroを使って見つけたほとんどの例は、Netbeansを使って自動的にWSDLから生成します。これは私を助けません。私は、WSIT、XWSSなどをあまり明確にも方向性も見ていない。 JBoss WS Metroはそれほど有望ではありませんでした。

誰でもこの作業を行っている経験がありますか、このタスクを達成する方法についての提案はありますか?私を正しい方向に向けることさえ助けになります。私はそれがJavaベースでなければならない以外の特定の技術に限定されていません。

答えて

8

私はこの問題を解決することになりましたが、私はそうする別の方向に行った。私のソリューションはCXF 2.1とそのJAX-WS実装を使用して、CXFのパワーと既存のSpringインフラストラクチャを組み合わせたものでした。私はCXFが必要とする数多くの瓶のために最初は懐疑的でしたが、最終的には最高かつ単純な解決策を提供しました。

CXF website for client configurationの例を適用して、私は春にカスタムCXF JAXWSネームスペースを使用し、Username Token Authentication(パスワードダイジェスト、ノンスとタイムスタンプ)とタイムスタンプ検証にOut Interceptorを使用しました。この作業を行うための唯一のステップは、各アウトバウンドSOAPリクエストに対して実行される独自のPassword Callbackハンドラを作成することでした。

SSLコンフィグレーションでは、具体的なhttp:conduitの名前でSSLを動作させることはできませんでしたが、プロダクション環境では推奨されない汎用目的を使用しなければなりませんでしたが、再びCXF and its SSL support via conduitsになりました。

以下は私の設定ファイルの例です。

春コンフィグファイル

<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クライアントのパスワードハンドラ

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

情報がWSDLに含まれていない場合は、その情報がWSDLによって記述されたサービスに含まれていることを確認してください。 WSDLは、サービスの使用に必要なセキュリティポリシーなど、サービスを記述するために必要なすべての情報を提供することを目的としています。

WSDLはどのプラットフォームから供給されましたか? WSDLが完全な記述ではない可能性はありますか?たとえば、であるWSDLで、別のWSDLに dを含めると、にセキュリティ情報を提供します。

+0

私はWSDLにアクセス権が与えられていないことを明確にしています。私が持っているドキュメントにはホール(タイムスタンプの言及はありません)がありますので、WSDL情報を捨てても私を驚かせることはできません。 –

+0

実際のサービスを呼び出すには、実際のWSDLが必要です。それはすべてそれについてです。 –

+0

したがって、WSDLはこれを省略してもサーバー上に実装される可能性はありませんか?サーバーは、Axisのいくつかのバージョンを使用するJava(おそらくJBossまたはWebsphere)です。 –

関連する問題