10

ユーザー名トークン認証 (パスワード ダイジェスト、ナンス、タイムスタンプ) とタイムスタンプ検証を備えた WS-Security と SSL 経由の WS-Addressing を使用する JAX-WS (Metro) を使用して、スタンドアロンの Java Web サービス クライアントを開発しようとしています。

私が扱う必要のある WSDL には、セキュリティ ポリシー情報が定義されていません。WSDL にこの情報が含まれていない場合に、このヘッダー情報を追加する方法 (正しい方法) を正確に理解することができませんでした。Metro を使用して見つけたほとんどの例は、Netbeans を使用して WSDL からこれを自動的に生成することを中心に展開していますが、これはまったく役に立ちません。私は WSIT や XWSS などを調べましたが、明確さや方向性はあまりありませんでした。JBoss WS Metro もまだあまり運が良くないように見えました。

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

4

3 に答える 3

8

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

クライアント構成にCXFWebサイトの例を採用し、Spring内でカスタムCXF JAXWS名前空間を使用し、ユーザー名トークン認証(パスワードダイジェスト、ナンス、タイムスタンプ)とタイムスタンプ検証にOutInterceptorを使用しました。これを機能させるための他の唯一のステップは、アウトバウンドSOAPリクエストごとに実行される独自のパスワードコールバックハンドラーを作成することでした。

SSL構成については、コンジットを介したCXFとそのSSLサポートに再度目を向けました。特定のhttp:conduit名でSSLを機能させることはできませんでしたが、実稼働環境では推奨されない汎用のものを使用する必要がありました。

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

Spring設定ファイル

<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);
    }
}
于 2009-05-06T15:36:41.753 に答える
0

WS-Security を使用して CXF でクライアントとサーバーを構成する方法を説明する投稿がここにあります: Spring と CXF を使用した JAX-WS Web サービス

于 2011-11-29T07:16:11.897 に答える
0

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

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

于 2009-03-30T22:21:01.980 に答える