4

我正在使用 Metro/WSIT 库编写 Java Web 服务客户端,而我需要访问的 Web 服务是 WCF 服务。(我几乎无法控制服务端和 WSDL。)

Web 服务使用传输级安全性 (SSL) 和使用安全令牌服务 (WS-Trust/WS-Security) 的联合安全模型来保护。我使用 Windows Identity Foundation 在 .NET 中轻松实现了客户端,首先发出安全令牌,然后使用 ( CreateChannelWithIssuedToken ) 方法向其他 Web 服务发出请求。

不过,使用 Metro/WSIT 时,我很难在 Java 中模仿这种行为。据我了解,由于 WSDL 中缺少 WS-Policy 信息,WSIT 不会启用与服务通信的安全处理。在发送请求之前,我通过操作 SOAP 请求标头来手动完成此操作,现在我收到的消息与我在 .NET 客户端收到的消息相同。

现在,我的问题是我收到以下错误:

Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: MustUnderstand headers:[{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security] are not understood
at com.sun.xml.ws.protocol.soap.MUTube.createMUSOAPFaultException(MUTube.java:148)
at com.sun.xml.ws.protocol.soap.ClientMUTube.processResponse(ClientMUTube.java:96)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:972)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:910)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:873)
at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:775)
at com.sun.xml.ws.client.Stub.process(Stub.java:429)
at com.sun.xml.ws.client.sei.SEIStub.doProcess(SEIStub.java:168)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:119)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:102)
at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:151)

因为 SOAP 响应在标头中有一个 Security 部分:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
    <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
        <u:Timestamp u:Id="_0">
            <u:Created>2012-05-14T21:20:08.782Z</u:Created>
            <u:Expires>2012-05-14T21:25:08.782Z</u:Expires>
        </u:Timestamp>
    </o:Security>
</s:Header>
<s:Body>
    ...

鉴于我无法修改 WSDL,有没有办法可以手动强制 Metro/WSIT 启用响应的安全处理,以免引发此异常?我不打算使用安全标头,并且响应的有效负载符合预期。我知道如果客户端不理解 mustunderstand="1" 的标头,我所看到的是正确的行为,但我正在寻找一种方法来抑制此异常。

我已经阅读了其他问题,例如这个问题,这似乎与我想要的很接近,但我还没有找到答案。任何建议/解决方案/等。不胜感激!

4

1 回答 1

3

我找到了一种解决方法(暂时适用),其中涉及插入 Metro 处理管道的自定义“管”。

I created a custom processing tube class that extends com.sun.xml.ws.api.pipe.helper.AbstractFilterTubeImpl, and overrides processResponse( Packet packet ), searching for headers with the name "Security" and calling packet.getMessage().getHeaders().understood( int ) for the index in the header list of the security header I found. This prevents processing down the tube from trying to understand the security headers (since the problem is that it doesn't).

After this I created a tube factory (implementing com.sun.xml.ws.assembler.TubeFactory) for my custom tube.

I then copied the contents of webservices-rt.jar/META-INF/metro-default.xml to META-INF/metro.xml in my project, and added a <tube-factory> element for my factory class; under <client-side> I put it just above the transport tube factory, and under <endpoint-side> I put it at the top of the list, above the transport tube factory.

Hopefully this helps anybody with a similar problem. Being able to add custom processing to the Metro pipeline seems immensely powerful but also dangerous; YMMV.

于 2012-05-16T18:09:20.110 回答