如何使用ClientInspector修改WCF消息头的MustUnderstand

我从WCF客户端调用非WCF服务。 WCF客户端包括“MustUnderstand”头属性设置为“1”。 这是典型的SOAP请求:

    2010-08-23T20:48:52.680Z 2010-08-23T20:53:52.680Z   blablabla blablabla      8/23/2010 4:48:51 PM 123   

现在,这是我回来的回应。

       soapenv:MustUnderstand WSWS3173E: Error: Did not understand "MustUnderstand" header(s):{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security   

注意关于MustUnderstand的部分没有被理解。

此服务的所有者已指出它们允许具有WSSE名称空间前缀但实际上不在XSD中的元素,并执行一些其他处理以阻止它们接受MustUnderstand =“1”,因此我必须找到一种方法使用MustUnderstand =“0”发送消息。

我尝试使用MessageHeader属性在MessageContract中为代理客户端更改此项,但这没有帮助。

接下来,我实现了一个自定义客户端消息检查器。 我为每个MSDN创建了一个自定义行为扩展元素和一个IEndpointBehavior的类,这些都是微不足道的,但这里是为了完整性:

  public class ExClientBehavior : IEndpointBehavior { #region IEndpointBehavior Members public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { // no op } public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { ExInspector inspector = new ExInspector(); clientRuntime.MessageInspectors.Add(inspector); } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { // no op } public void Validate(ServiceEndpoint endpoint) { // no op } #endregion } public class ExClientBehaviorExtensionElement : BehaviorExtensionElement { public override Type BehaviorType { get { return typeof(ExClientBehavior); } } protected override object CreateBehavior() { return new ExClientBehavior(); } } 

现在是实际的督察:

  public class ExInspector : IClientMessageInspector { #region IClientMessageInspector Members public void AfterReceiveReply(ref Message reply, object correlationState) { // no op return; } public object BeforeSendRequest(ref Message request, IClientChannel channel) { MessageBuffer buffer = request.CreateBufferedCopy(int.MaxValue); Message newMessage = buffer.CreateMessage(); newMessage.Headers.RemoveAt(0); newMessage.Headers.Add(MessageHeader.CreateHeader ( request.Headers[0].Name, request.Headers[0].Namespace, string.Empty, false, string.Empty, request.Headers[0].Relay ) ); request = newMessage; return null; } #endregion } 

如您所见,我通过缓冲副本创建一个新请求,然后删除安全标头(只有一个标头)并添加一个MustUnderstand设置为false的新请求(为什么我这样做?MessageHeader.MustUnderstand是只读的)。 我在这个方法中设置了一个断点,实际上,添加了新的头,newMessage被写回请求,newMessage.Headers [0] .MustUnderstand以及request.Headers [0] .MustUnderstand都是假的这个方法结束了。

但是,发送到服务的消息仍然包括标题上的MustUnderstand =“1”!

这是包含上述行为的app.config:

                              

所以我的问题是:是否有可能在上述传出消息或类似方式上更改MustUnderstand? 或者,在检查员替换安全标头后,它是否会在管道中被强制更改为true?

注意:服务所有者说他们只知道在.NET中使用此服务的另一个组织,并且该消费者必须从头开始抛弃WCF和WSE并创建SOAP消息 – 并从头开始处理回复,可能使用POX POST或其他一些。 我们真的更愿意避免这种情况,因为我们需要在服务上调用许多操作。

此外,我们需要保持消息的正文和属性完整。

任何帮助将非常感激!!

我想知道如果供应商不遵守它们,为什么存在互操作性标准。 如果客户端检查器不起作用,您可以尝试实现自定义消息编码器并在那里修改标头。

编辑:

这里的问题是,如果您在同一时间声明服务不必理解带有凭据的标头=不必使用它们,那么为什么要发送用户凭据进行身份validation。 你真的需要它们吗?

还有其他方法取决于您的要求。 你需要时间戳吗? 是否在服务器上检查了时间戳? 您是否拥有所有呼叫的单个用户,或者您是否必须在呼叫之间区分用户?

如果您不需要时间戳或时间戳未选中,并且您只有单个用户名和密码,则最简单的方法是不使用TranportWithMessageCredential安全模式。 使用纯传输,并在客户端端点配置中放置标头描述,如:

      User Pwd123      

如果您有多个用户名,或者您需要使用实际数据的实时时间戳,则可以使用相同的方法,但您可以在代码中创建自定义标头而不是静态配置,以避免WCF安全。 这可以使用消息检查器完成。