有一个Java服务器的web服务, 只是遵循SOAP Message Security 1.0协议, 没有证书,使用Http协议,
调用的时候遇到了一些麻烦.
1. 开始用WCF调用, 始终不能成功, WCF使用UserName验证的时候要么使用Https协议,要么使用X509证书.
他严格的要求传输时的安全性, 所以不能使用UsernameToken Profile 1.0 对用户名和密码处理。
应该是有别的办法的, 目前没研究明白.
2. 使用WSE3.0.
这个组件.net3.5中没有, 要单独安装, 在WebConfig添加一些配置项.
其中有几个关键的地方:
<messaging>
<mtom serverMode="optional" clientMode="On" />
</messaging>
这里需要开启MTOM协议的支持, 服务端是自己选择, 客户端是开启. 主要是处理附件上传这类大文件.
如果不开启,总是报错误: 返回的数据是application/xop+xml 类型, 而应该是”text/xml”.
VS2008不支持WSE3.0组件, 引用WEBService 后,要手动修改Reference.cs的继承类为Microsoft.Web.Services3.WebServicesClientProtocol.
在wse3policyCache.config文件中对WSE扩展定义, 其实就是可以在Soap请求发出前, 进行附加的处理步骤.
这里自己添加了一个组件. <extension name="RemoveTimestamp" type="WSSE3.UsernameClientAssertion, WSSE3"/>
这个SecurityPolicyAssertion的作用是修改SaopHeader中的内容.
默认发出的Header中的Security段是这样的:
<wsse:Security soap:mustUnderstand="1">
<wsu:Timestamp wsu:Id="Timestamp-0a44f33a-9bb0-4cc4-a4a2-e22e622c9daa">
<wsu:Created>2009-06-11T06:51:49Z</wsu:Created>
<wsu:Expires>2009-06-11T06:56:49Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SecurityToken-e118d95f-f4a8-4e12-8102-4b24a66d39a7">
<wsse:Username>某某用户</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">123</wsse:Password>
<wsse:Nonce>meHEDYrJuLsimiAxFZ1F2Q==</wsse:Nonce>
<wsu:Created>2009-06-11T06:51:49Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
而期望的Header(接口文档)中没有< wsu:Timestamp >这段, 不移除会调用失败.
通过实现SoapFilter类, 可以在Soap请求发出或者接受时进行处理.
public override Microsoft.Web.Services3.SoapFilterResult ProcessMessage(SoapEnvelope envelope)
{
XmlNamespaceManager mgr = new XmlNamespaceManager(envelope.NameTable);
mgr.AddNamespace("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
mgr.AddNamespace("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
XmlNode securityNode = envelope.Header.SelectSingleNode("wsse:Security", mgr);
XmlNode timestamp = envelope.Header.SelectSingleNode("wsse:Security/wsu:Timestamp", mgr);
securityNode.RemoveChild(timestamp);
return SoapFilterResult.Continue;
}
这段代码, 将Timestamp移除。
另外我们可以打开追踪功能,这样调试问题就方便许多了。
<diagnostics>
<trace enabled="true" input="InputTrace.webinfo" output="OutputTrace.webinfo" />
<detailedErrors enabled="true" />
</diagnostics>
会在项目下生成两个文件,里面记录了详细的信息,input是输入,output是发出的。
总结: .net下调用Java的安全Web服务, 差异性有时让人不知道哪里出错, 很难理出思路.