2012-03-28 12 views
5

Escribo un cliente WCF que consume un servicio web que no sea .Net, usando WS-Security. La respuesta del servicio contiene un encabezado de Seguridad con mustUnderstand configurado en verdadero.Cliente WCF: cómo procesar o ignorar un elemento de encabezado MustUnderstand?

Utilizando un ServiceModelListener, veo datos reales que regresan del servicio. El cliente WCF falla, sin embargo, porque no está procesando el encabezado de Seguridad.

<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 mensaje de error Cliente:

La cabecera 'Seguridad' del espacio de nombres 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' no fue comprendido por el destinatario de este mensaje, haciendo que el mensaje a no ser procesada. Este error generalmente indica que el remitente de este mensaje ha habilitado un protocolo de comunicación que el receptor no puede procesar. Asegúrese de que la configuración del enlace del cliente sea coherente con el enlace del servicio.

Mi cliente WCF no necesita ninguna información de marca de tiempo. ¿Hay una manera fácil de stub en una rutina de procesamiento? Ya he intentado extender la clase de respuesta & agregando una propiedad [MessageHeader].

EDIT:

preguntó otro modo: ¿Cómo se implementa un cliente que acepte WCF elementos de la cabecera personalizados que están marcados deben entender?

Respuesta

1

Existen diferentes estándares de WS-Security. Puede ser que tenga sentido cambiar la vinculación en el lado del cliente, ya que basicHttpBinding y wsHttpBindings funcionan con diferentes estándares de seguridad.

+1

Gracias, pero el servicio solo admite basicHttpBinding. –

2

Me encontré con un problema similar. No estoy seguro de si esto es útil o no.

MSDN WCF extensibilidad

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

La configuración aquí se basa Certificado, Oracle Application Server 10g, y .Net que consumen los servicios. Usar SOAPUi fue muy útil al tratar de descubrir qué estaba sucediendo con la Solicitud y luego la respuesta.

No he intentado modificar el código para usar basicHttpBinding, pero utilicé WSHttpBinding como la base de mi configuración en el código. Entonces utilizado

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(); 

bucle a través de la TextMessageEncodingBindingElement para establecer Soap11 y AddressingVersion a Ninguna.

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); 
     } 

Utilicé ChannelFactory y agregué un EndPoint Behavior para un inspector de mensajes. En este momento, yo tenía control de la solicitud y podía agregar el encabezado apropiado y modificar el mustUnderstand en la Acción.

Usando SOAPUi tomé mi Message.ToString() y lo puse en SOAPUI y probé la solicitud.Una vez que los elementos necesarios se agregaron a la solicitud, se determinó que el servidor de la OEA no respondía con todos los elementos necesarios. Usando el inspector de mensajes para la respuesta, modifiqué el mensaje para incluir los encabezados que faltan. No recuerdo dónde encontré el código base para el inspector de mensajes, pero necesitaría modificar su código para utilizarlo correctamente.

Para mi ejemplo aquí hay algunos fragmentos.

Para el mensaje transformar en

public object BeforeSendRequest 

que necesitaba para modificar el encabezado, así que usar un bucle for Tomé el XElement y añade la cabecera OASIS y añadió una Para cabecera.

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); 

También tuve que modificar el encabezado de Acción

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

Mi problema era que el servicio no respondió con una cabecera de Acción

Así que en el

public void AfterReceiveReply 

Llamé a mi TransformReply devolver tipo de mensaje con algo como el siguiente. Es posible que necesite modificar los valores de la cadena. Vacío, pero esto es solo un ejemplo.

...

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

...

yo realmente sugerir el uso de una herramienta como SOUPUI beable a meterse con el sobre y ver la respuesta. Si realiza SSL, deberá crear un archivo cacert y colocarlo en SSLSettings de las preferencias.

+0

¡Gracias Adam! parece una información interesante Sin embargo, ahora pasé a un trabajo de consultoría diferente, por lo que ya no puedo probar cosas en contra de ese sistema. Fyi, anteriormente el cliente finalmente resolvió el problema a través de un enfoque arquitectónico diferente. –

Cuestiones relacionadas