.NET调用SOAP服务报错:无法解析签名URI '#MsgBody'
解决System.ServiceModel.Security.MessageSecurityException: Cannot resolve signature URI '#MsgBody'问题
核心原因
Java与.NET的WS-Security实现对SOAP Body的签名引用URI约定存在差异:Java服务返回的签名引用中使用#MsgBody作为Body标识,但WCF默认期望的是#Body(或无特殊前缀的Body元素ID),导致WCF无法匹配到对应签名目标,触发验证失败。
解决方案
1. 自定义MessageInspector修改响应签名引用URI
实现IClientMessageInspector,在客户端接收响应后修改XML中的签名引用URI,将#MsgBody替换为WCF可识别的#Body:
public class FixSignatureUriInspector : IClientMessageInspector { public object BeforeSendRequest(ref Message request, IClientChannel channel) { return null; } public void AfterReceiveReply(ref Message reply, object correlationState) { // 将响应转为XML文档进行修改 var doc = new XmlDocument(); using (var reader = reply.GetReaderAtBodyContents()) { doc.Load(reader); } // 定位签名引用的URI属性,替换#MsgBody为#Body XmlNamespaceManager nsMgr = new XmlNamespaceManager(doc.NameTable); nsMgr.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#"); var referenceNodes = doc.SelectNodes("//ds:Reference/@URI", nsMgr); foreach (XmlNode node in referenceNodes) { if (node.Value == "#MsgBody") { node.Value = "#Body"; } } // 重新构建Message返回 var newReply = Message.CreateMessage(reply.Version, null, doc.CreateNavigator()); newReply.Headers.CopyHeadersFrom(reply.Headers); newReply.Properties.CopyProperties(reply.Properties); reply = newReply; } }
将该Inspector添加到客户端EndpointBehavior中:
public class FixSignatureUriBehavior : IEndpointBehavior { public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { clientRuntime.MessageInspectors.Add(new FixSignatureUriInspector()); } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { } public void Validate(ServiceEndpoint endpoint) { } }
创建客户端代理时绑定该Behavior:
var client = new YourSoapServiceClient(); client.Endpoint.Behaviors.Add(new FixSignatureUriBehavior()); // 调用服务方法 client.YourServiceMethod();
2. 临时关闭Body签名验证(仅测试用,不推荐)
若仅需临时验证业务逻辑,可修改配置关闭Body签名验证,但会降低安全性:
在客户端配置的<binding>节点下添加:
<security mode="Message"> <message clientCredentialType="..." algorithmSuite="..."> <claimTypeRequirements> <add claimType="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" isOptional="true" /> </claimTypeRequirements> <secureConversationBootstrap /> <!-- 跳过Body签名验证配置 --> <protectionLevel>Sign</protectionLevel> <enableUnsecuredResponse>true</enableUnsecuredResponse> </message> </security>
3. 验证修改效果
修改后调用服务,通过Fiddler确认响应已被正确修改,WCF不再抛出签名验证异常,同时业务响应可正常解析。
内容的提问来源于stack exchange,提问作者dual
相关产品推荐
相关产品推荐

