0

opentravel.org OTA XML 要求を受け入れ、それに応じて応答する tomcat Web サービスがあります。これは、JibX OTA クラスを使用します。

これまでのところ、サービスのユーザーは POX を使用しており、非常にうまく機能しますが、新しいユーザーは SOAP を使用して、このように SOAP ヘッダーにセキュリティ資格情報を追加したいと考えています (POS xml フラグメントを配置する代わりに)...

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <wsse:Security soap:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org        /wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <wsse:UsernameToken>
        <wsse:Username>USERNAME</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-    wss-username-token-profile-1.0#PasswordText">SECRET</wsse:Password>
      </wsse:UsernameToken>
    </wsse:Security>
  </soap:Header>

したがって、リクエストを認証するには、サービス実装クラス内からヘッダーにアクセスする必要があると思います。

SOAPヘッダーの例をチェックアウトしました。これは、inContextも含めることでヘッダーにアクセスできることを示していると思います。

public RoomListRS list(RoomListRQ roomListRQ, InContext inCtx){
....
}

したがって、このメソッド内でこれを行うことができます...

Security security = (Security ) inCtx.getAttribute("security");

その中のユーザー名トークンにアクセスできます

...サービスでこれを指定すると...

<service name="OTAService">
  <service-class>com.xx.webservice.ota.HotelServiceImpl</service-class>
  <operation method="list"/>
  <handler-class class="org.jibx.ws.io.handler.ContextAttributeUnmarshallingInHandler">
    <constructor-arg value="com.xx.shared.soap.security.Security"/>
    <constructor-arg value="security"/>
  </handler-class>
</service>

私はそれを正しく理解していますか?

そのため、Security クラスを作成しましたが、ヘッダー内の何かにアクセスできることを証明するために、すべての名前空間を省略して開始しました。このようなフラグメントを持つことに基づいて...

    <Security>
      <UsernameToken>
        <Username>USERNAME</Username>
        <Password>SECRET</Password>
      </UsernameToken>
    </Security>

だから私はbindgenでバインディングを作成し、コンパイルしてからsoapUIで呼び出しました

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.opentravel.org/OTA/2003/05">
     <soapenv:Header>
     <Security>
      <UsernameToken>
        <Username>USERNAME</Username>
        <Password>SECRET</Password>
      </UsernameToken>
    </Security>
  </soapenv:Header>
   <soapenv:Body>
<OTA_HotelRoomListRQ xmlns="http://www.opentravel.org/OTA/2003/05" Version="2.0">
....
</OTA_HotelRoomListRQ>
</soapenv:Body>
</soapenv:Envelope>

しかし、コンテキストから Security オブジェクトを取得しようとすると、null になります。

スティックの端が間違っていますか?

もっと SOAPY を使用して、別のエンドポイントを持つ別のサービスを作成する必要がありますか?

私がやろうとしていることは、JibX WS と inHandler では不可能ですか?

どんなコメントでも大歓迎です。


私の質問に答えてくれてありがとう。

私はあなたが追加したものを調べようとしています。あなたのカスタマイズと xsd を使用して、Java ソースと binding.xml を作成しました。

クラスをコンパイルしてバインドしようとしていますが、次のエラーが発生します。

C:\Java\wsse>java org.jibx.binding.generator.BindGen org.oasisopen.docs.wss.oasis200401wsswssecuritysecext1.SecurityHeaderType
Exception in thread "main" java.lang.IllegalStateException: No way to handle type java.lang.Object, referenced from org.oasisopen.docs.wss.oasis200401wsswssecuritysecext1.SecurityHeaderType
    at org.jibx.binding.generator.BindGen.expandReferences(BindGen.java:227)
    at org.jibx.binding.generator.BindGen.findReferences(BindGen.java:1010)
    at org.jibx.binding.generator.BindGen.generate(BindGen.java:1124)
    at org.jibx.binding.generator.BindGen.main(BindGen.java:1302)

bindgen のカスタマイズを調べて、この問題に対応する唯一の手がかりになるかどうかを確認します。これをどのように回避したか教えていただけますか?

再度、感謝します。

4

1 に答える 1

0

WS-Security のユーザー名/パスワード ヘッダー用の製品コードを共有できます。コードが機能しない理由はわかりませんが、これが役立つかもしれません。

次のカスタマイズを使用して、oasis-200401-wss-wssecurity-secext-1.0.xsd スキーマから WS-Security コードとバインディングを生成しました。

<!--  Contains customization elements for code generation from WS Security schema -->
<schema-set show-schema="false" generate-all="false" xmlns:xs="http://www.w3.org/2001/XMLSchema" line-width="120">
  <schema name="oasis-200401-wss-wssecurity-secext-1.0.xsd" generate-all="true" prefer-inline="true" any-handling="mapped">
    <class-decorator class="org.jibx.schema.codegen.extend.CollectionMethodsDecorator" />
  </schema>
</schema-set>

次に、次のもので構築されます。

<target name="codegen-wss" description="Regenerate JiBX bindings and generated code for WS-Security schema">
  <echo message="Running code generation from schema" />
  <mkdir dir="${gen.src.dir}" />
  <java classname="org.jibx.schema.codegen.CodeGen" fork="yes" classpathref="build.classpath" failonerror="true">
    <arg value="-c" />
    <arg value="custom_jibx_gen_wssec.xml" />
    <arg value="-t" />
    <arg value="${gen.src.dir}" />
    <arg value="wsdl/wssec/oasis-200401-wss-wssecurity-secext-1.0.xsd" />
  </java>
  <move file="${gen.src.dir}/binding.xml" tofile="${wssec.binding.file}" failonerror="true" />
</target>

とバインド:

<target name="compile" depends="init" description="Compile the source code and run JiBX binding compiler">
  <mkdir dir="${dest.dir}" />
  <javac srcdir="${src.dir}:${gen.src.dir}" destdir="${dest.dir}" deprecation="on">
    <classpath refid="build.classpath" />
  </javac>
  <bind binding="${gen.src.dir}/xxx-binding.xml">
    <classpath path="${dest.dir}" />
  </bind>
  <bind binding="${wssec.binding.file}">
    <classpath path="${dest.dir}" />
  </bind>
</target>

サーブレットの Spring 構成は、InHandler を定義します。

<property name="handlerDefinitions">
  <list>
    <bean class="org.jibx.ws.server.HandlerDefinition" >
      <description>Handler for inbound WS/Security header</description>
      <property name="className" value="org.jibx.ws.io.handler.ContextAttributeUnmarshallingInHandler" />
      <property name="args">
        <list>
          <value>org.oasisopen.docs.wss.oasis200401wsswssecuritysecext1.SecurityHeaderType</value>
          <value>wssecurity.header</value>
        </list>
      </property>
    </bean>

そして、エンドポイントは以下を使用してヘッダーを取得します。

public ServiceRequestReceipt processRequest(ServiceRequest request, InContext inCtx, OutContext outCtx) 
    throws WsException {
    SecurityHeaderType securityHeader = (SecurityHeaderType) inCtx.getAttribute("wssecurity.header");

securityHeader を使用するコードは次のようになります。

        if (securityHeader == null) {
            throw new AuthenticationException("No WS-Security header found");
        }

        List<Object> securityHeaderTypes = securityHeader.getSecurityHeaderTypes();
        if (securityHeaderTypes == null || securityHeaderTypes.size() == 0) {
            throw new AuthenticationException("WS-Security header appears to be empty");
        }

        UsernameTokenType usernameToken = null;
        try {
            usernameToken = (UsernameTokenType) securityHeaderTypes.get(0);
        } catch (ClassCastException e) {
            throw new AuthenticationException("Expected UsernameToken in WS-Security header");
        }

        AttributedString usernameAttStr = usernameToken.getUsername();
        if (usernameAttStr == null) {
            throw new AuthenticationException("Expected Username in WS-Security header");
        }

        String username = usernameAttStr.getString();
        if (!username.equals(retailer.getRetailerUsername())) {
            throw new AuthenticationException("Invalid username in WS-SecurityHeader");
        }
        List<Object> any = usernameToken.getAny();
        if (any == null) {
            throw new AuthenticationException("Expected Password element in WS-Security header");
        }
        PasswordString passwordString = null;
        for (Iterator iterator = any.iterator(); iterator.hasNext();) {
            try {
                passwordString = (PasswordString) iterator.next();
            } catch (ClassCastException ignore) {
                logger.debug("Found non password string object");
            }
        }
        if (passwordString == null) {
            throw new AuthenticationException("Expected Password in WS-Security header");
        }
        if (passwordString.getAttributedString() == null) {
            throw new AuthenticationException("Expected Password AttributedString in WS-Security header");
        }

        String password = passwordString.getAttributedString().getString();
        if (!password.equals(retailer.getRetailerPassword())) {
            throw new AuthenticationException("Invalid password in WS-SecurityHeader");
        }

それが役立つことを願っています!

于 2012-05-04T22:00:37.797 に答える