Я звоню в службу, отличную от WCF, из клиента WCF.Клиент WCF включает атрибут заголовка «MustUnderstand», установленный в «1».Вот типичный запрос SOAP:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/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>2010-08-23T20:48:52.680Z</u:Created>
<u:Expires>2010-08-23T20:53:52.680Z</u:Expires>
</u:Timestamp>
<o:UsernameToken u:Id="uuid-72ea0c0a-43aa-43b2-bed7-c2da13624105-1">
<o:Username>blablabla</o:Username>
<o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">blablabla</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<HeartbeatRequest xmlns="http://removed">
<DateTime xmlns="">8/23/2010 4:48:51 PM</DateTime>
<Message xmlns="">123</Message>
</HeartbeatRequest>
</s:Body>
Теперь вот ответ, который я получаю за это.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<Misunderstood qname="o:Security" xmlns="http://www.w3.org/2002/06/soap-faults" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" />
</soapenv:Header>
<soapenv:Body>
<soapenv:Fault xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<faultcode>soapenv:MustUnderstand</faultcode>
<faultstring>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</faultstring>
</soapenv:Fault>
</soapenv:Body>
Обратите внимание на частьо том, что MustUnderstand непонятно.
Владелец этого сервиса указал, что он разрешает элементы, которые имеют префикс пространства имен WSSE, но на самом деле не находятся в XSD, и выполняет некоторую другую обработку, которая не позволяет им принимать MustUnderstand= "1", поэтому мне нужно найти способ отправки сообщений с MustUnderstand = "0".
Я попытался изменить это в MessageContract для прокси-клиента с помощью атрибута MessageHeader, но это не помогло.
Далее я реализовал пользовательский инспектор сообщений клиента.Я создал классы для каждого 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, который включает в себяПоведение выше:
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="WebServiceSOAP" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Basic" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint
address="https://removed"
behaviorConfiguration="ovrExClientBehavior"
binding="basicHttpBinding"
bindingConfiguration="WebServiceSOAP"
contract="EWebService.EWebService"
name="WebServiceSOAP" />
</client>
<extensions>
<behaviorExtensions>
<add name="exClientBehavior" type="ExMessageInspector.ExClientBehaviorExtensionElement, ExMessageInspector, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
<behaviors>
<endpointBehaviors>
<behavior name="ovrExClientBehavior">
<exClientBehavior />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
Итак, мой вопрос: возможно ли изменить MustUnderstand на исходящем сообщении, как описано выше, или подобным образом?Или это принудительно изменяется обратно на true позже в конвейере, после того, как инспектор заменит заголовок безопасности?
Примечание: владелец службы говорит, что ему известна только одна другая организация, использующая эту службу в .NET,и что этот потребитель должен был по существу выбросить WCF и WSE и создать сообщения SOAP - и обработать ответы - с нуля, возможно, используя POX POST или что-то подобное.Мы действительно предпочли бы избежать этого, так как нам нужно вызвать ряд операций над службой.
Кроме того, нам нужно сохранить тело и свойства сообщения без изменений.
Любая помощь будетбыть очень ценным !!