2012-03-28 24 views
5

Piszę klienta WCF, który pobiera usługę sieci Web innej niż .Net za pomocą WS-Security. Odpowiedź usługi zawiera nagłówek Security z ustawieniem mustUnderstand na wartość true.Klient WCF - jak przetwarzać lub ignorować element nagłówka MustUnderstand?

Korzystanie z ServiceModelListener, widzę rzeczywiste dane wraca z usługi. Klient WCF nie powiedzie się jednak, ponieważ nie przetwarza nagłówka Security.

<env:Header> 
<wsse:Security env:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> 
<wsu:Timestamp wsu:Id="timestamp"> 
<wsu:Created>2012-03-28T13:43:54.474Z</wsu:Created> 
<wsu:Expires>2012-03-28T13:48:54.474Z</wsu:Expires> 
</wsu:Timestamp> 
</wsse:Security> 
</env:Header> 

WCF Client Error Message:

Nagłówek 'Bezpieczeństwo' z przestrzeni nazw 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' nie został zrozumiany przez odbiorcę tej wiadomości, co powoduje, że wiadomość nie może zostać przetworzony. Ten błąd zwykle oznacza, że ​​nadawca tej wiadomości włączył protokół komunikacyjny, którego odbiornik nie może przetworzyć. Upewnij się, że konfiguracja powiązania klienta jest zgodna z powiązaniem usługi.

Mój klient WCF nie potrzebuje żadnych informacji o sygnaturze czasowej. Czy istnieje prosty sposób na utrwalenie w procedurze przetwarzania? Próbowałem już rozszerzyć klasę odpowiedzi & dodając właściwość [MessageHeader].

EDIT:

zadawane inny sposób: w jaki sposób zaimplementować WCF klienta, który akceptuje niestandardowych nagłówków, które są oznaczone muszą zrozumieć?

Odpowiedz

1

Istnieją różne standardy WS-Security. Może być sensu zmiana wiązania po stronie klienta, ponieważ basicHttpBinding i wsHttpBindings działają z różnymi standardami bezpieczeństwa.

+1

Dzięki, ale usługa obsługuje tylko basicHttpBinding. –

2

Wpadłem na podobny problem. Nie jestem pewien, czy jest to przydatne, czy nie.

MSDN WCF Rozszerzalność

http://blogs.msdn.com/b/carlosfigueira/archive/2011/04/19/wcf-extensibility-message-inspectors.aspx

Konfiguracja tutaj opiera certyfikatu, Oracle Application Server 10g i .Net spożywać usługi. Używanie SOAPUi było bardzo przydatne podczas próby ustalenia, co dzieje się z Żądaniem, a następnie odpowiedzią.

Nie próbowałem modyfikować kodu, aby użyć funkcji basicHttpBinding, ale użyłem WSHttpBinding jako podstawy mojej konfiguracji w kodzie. Następnie wykorzystywane

WSHttpBinding binding = new WSHttpBinding() 
     { 
      CloseTimeout = new TimeSpan(0, 1, 0), 
      OpenTimeout = new TimeSpan(0, 1, 0), 
      SendTimeout = new TimeSpan(0, 1, 0), 
      AllowCookies = false, 
      BypassProxyOnLocal = false, 
      HostNameComparisonMode = HostNameComparisonMode.StrongWildcard, 
      MaxBufferPoolSize = 524288, 
      MaxReceivedMessageSize = 65536, 
      MessageEncoding = WSMessageEncoding.Text, 
      UseDefaultWebProxy = false, 
      ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas() 
      { 
       MaxDepth = 32, 
       MaxArrayLength = 16384, 
       MaxBytesPerRead = 4096, 
       MaxNameTableCharCount = 16384, 
       MaxStringContentLength = 8192 
      } 
     }; 
     binding.Security.Mode = SecurityMode.Transport; 
     binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate; 
     binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None; 
     binding.Security.Transport.Realm = string.Empty; 
     binding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate; 
     binding.Security.Message.EstablishSecurityContext = true; 
     binding.Security.Message.NegotiateServiceCredential = true; 

     CustomBinding customBinding = new CustomBinding(); 
     BindingElementCollection collection = binding.CreateBindingElements(); 

przelotowe dla TextMessageEncodingBindingElement aby ustawić Soap11 i AddressingVersion sobie równych.

foreach (BindingElement element in collection) 
     { 
      if (typeof(TextMessageEncodingBindingElement) == element.GetType()) 
      { 
       TextMessageEncodingBindingElement item = element as TextMessageEncodingBindingElement; 
       if (null != item) 
       { 
        item.MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap11, AddressingVersion.None); 
        customBinding.Elements.Add(item); 
       } 
      } 
      else 
       customBinding.Elements.Add(element); 
     } 

Użyłem ChannelFactory i dodałem zachowanie EndPoint dla Inspektora wiadomości. W tym momencie miałem kontrolę nad żądaniem i mogłem dodać odpowiedni nagłówek i zmodyfikowałem mustUnderstand w Akcji.

Korzystanie z SOAPUi Wziąłem mój Message.ToString() i umieścić go w SOAPUI i przetestowane żądanie.Po dodaniu potrzebnych pozycji do żądania ustalono, że serwer OAS nie odpowiadał wszystkimi niezbędnymi elementami. Używając inspektora wiadomości do odpowiedzi, zmodyfikowałem wiadomość tak, aby zawierała brakujące nagłówki. Nie pamiętam, gdzie znalazłem kod bazowy dla inspektora wiadomości, ale musisz zmodyfikować swój kod, aby poprawnie go wykorzystać.

Na mój przykład tutaj są niektóre snippets.

Do wiadomości przekształcenia w

public object BeforeSendRequest 

musiałem zmodyfikować nagłówek, więc za pomocą pętli for złapałem Xelement i dodaje nagłówek OASIS oraz dodano Aby cel.

XNamespace xmlns = "http://schemas.xmlsoap.org/soap/envelope/"; 
       XElement securityHeader = new XElement(
        xmlns + "Security", 
        new XAttribute(xmlns + "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"), 
        new XAttribute(xmlns + "xmlns", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"), 
        new XAttribute(xmlns + "mustUnderstand", "0")); 
       element.Add(securityHeader); 

miałem też zmodyfikować Akcja żniwna

else if (localName.Equals("Action", StringComparison.InvariantCultureIgnoreCase)) 
      { 
       foreach (XAttribute a in element.Attributes()) 
       { 
        if (a.Name.LocalName == "mustUnderstand") 
         a.Value = "0"; 
       } 
      } 

Moim problemem było to, że obsługa nie odpowiedzieć za pomocą Action Header

Więc w

public void AfterReceiveReply 

Wywołałem moją wiadomość typu ReturnReply zwracającą z czymś podobnym do następującego. Może być konieczne zmodyfikowanie wartości ciągu.Empty, ale to tylko przykład.

...

Message reply = Message.CreateMessage(message.Version, null, reader); 
     reply.Headers.Add(MessageHeader.CreateHeader("Action", string.Empty, string.Empty, false)); 
     reply.Properties.CopyProperties(message.Properties); 

...

bym naprawdę sugerują, za pomocą narzędzia takiego jak SOUPUI do beable bałagan z kopertą i zobaczyć odpowiedź. Jeśli korzystasz z protokołu SSL, musisz utworzyć plik cacert i umieścić go w ustawieniach protokołu SSL preferencji.

+0

Dzięki Adam! wygląda na ciekawe informacje. Przeniosłem się teraz na inne zlecenie konsultingowe, więc nie mogę już wypróbować tego systemu. Fyi, wcześniej klient ostatecznie rozwiązał problem poprzez inne podejście architektoniczne. –