我正在使用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“的头,我看到的是正确的行为,但我正在寻找一种方法来抑制这种异常。
我已经阅读了其他问题,例如this one,它们似乎与我想要的很接近,但我还没有找到答案。非常感谢您的任何建议/解决方案/等!
发布于 2012-05-17 02:09:20
我发现了一种解决方法(暂时适用),它涉及到插入Metro处理管道的自定义“管”。
我创建了一个自定义处理管类,它扩展了com.sun.xml.ws.api.pipe.helper.AbstractFilterTubeImpl,覆盖了processResponse( Packet packet ),搜索名称为" security“的标头,并为我找到的安全标头的标头列表中的索引调用packet.getMessage().getHeaders().understood( int )。这阻止了管道中的处理试图理解安全标头(因为问题是它不理解)。
在此之后,我为我的自定义管道创建了一个管道工厂(实现com.sun.xml.ws.assembler.TubeFactory)。
然后,我将webservices-rt.jar/META-INF/metro-default.xml的内容复制到我的项目中的META-INF/metro.xml中,并为我的工厂类添加了一个<tube-factory>元素;在<client-side>下,我将它放在传输管工厂的正上方,在<endpoint-side>下,我将它放在列表的顶部,在传输管工厂的上方。
希望这能帮助任何有类似问题的人。向Metro管道添加自定义处理似乎非常强大,但也很危险;YMMV。
https://stackoverflow.com/questions/10591777
复制相似问题