Forma correcta de comunicarse PSES Usernametoken para webservice SOAP

Estoy tratando de consumir un servicio web a través de su wsdl correspondiente. Este servicio depende de autenticación que se ajusten a Seguridad En Servicios Web Básica Perfil De Seguridad De 1.0 incluyendo la correcta xmls espacio de nombres de http://docs.oasis-open.org/wss/2004/01/oasis-200401wss-wssecurity-secext-1.0.xsd deben ser incluidos en la solicitud.

Ejemplo:

<wsse:UsernameToken xmlns:wsse='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' >
   <wsse:Username>
      Bob
   </wsse:Username>
   <wsse:Password Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText'>
      1234
   </wsse:Password>
</wsse:UsernameToken>

Mis primeros intentos fueron a lo largo de las líneas de Add Service Reference la orientación del wsdl y de la que genera el uso de proxies como tales

ServicePointManager.ServerCertificateValidationCallback = 
    (object s, X509Certificate certificate, X509Chain chain,
                     SslPolicyErrors sslPolicyErrors) => true;

var basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
basicHttpBinding.Security.Transport.ClientCredentialType = 
                                                HttpClientCredentialType.Basic;

var endpoint = new EndpointAddress("https://secure-ausomxana.crmondemand.com/..."

using (var client = new ContactClient(basicHttpBinding, endpoint))
{

    var credential = client.ClientCredentials.UserName;
    credential.UserName = "bob";
    credential.Password = "1234";

    var input = ...    
    var output = client.ContactQueryPage(input);
}

Sin embargo tratando de interrogar a los mensajes SOAP con Fiddler veo que no UsernameToken elemento ha sido añadido.

¿Cuál es la forma correcta para cumplir con este contrato?

Edición: tras la respuesta de @John Saunders he tratado de cambiar mi código para utilizar un wsHttpBinding

var wsHttpBinding = new WSHttpBinding(SecurityMode.Transport);
wsHttpBinding.Security.Transport.ClientCredentialType =
                                         HttpClientCredentialType.Basic;

Usando este enlace el mensaje SOAP se convierte en

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
  <s:Header>
    <a:Action s:mustUnderstand="1">document/urn:crmondemand/ws/ecbs/contact/10/2004:ContactQueryPage</a:Action>
    <a:MessageID>urn:uuid:17807f44-1fcasfdsfd</a:MessageID>
    <a:ReplyTo>
      <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
    </a:ReplyTo>
    <a:To s:mustUnderstand="1">https://secure-ausomxana.crmondemand.com/Services/Integration</a:To>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <ContactQueryPage_Input xmlns="urn:crmondemand/ws/ecbs/contact/10/2004">
      <ListOfContact xmlns="urn:/crmondemand/xml/Contact/Query">
        <Contact>
          <Id>1-asdfd</Id>
        </Contact>
      </ListOfContact>
    </ContactQueryPage_Input>
  </s:Body>
</s:Envelope>

Esto agrega el elemento de Encabezado, como contraposición a la wsse:UsernameToken elemento de referencia el original mensaje soap utilizando el BasicHttpBinding es

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <ContactQueryPage_Input xmlns="urn:crmondemand/ws/ecbs/contact/10/2004">
      <ListOfContact xmlns="urn:/crmondemand/xml/Contact/Query">
        <Contact>
          <Id>1-asdfds</Id>
        </Contact>
      </ListOfContact>
    </ContactQueryPage_Input>
  </s:Body>
</s:Envelope>

Si puedo cambiar el enlace a

var wsHttpBinding = new WSHttpBinding(SecurityMode.TransportWithMessageCredential);
wsHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
wsHttpBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;

El mensaje SOAP que me salga es

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
  <s:Header>
    <a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT</a:Action>
    <a:MessageID>urn:uuid:eeb75457-f29e-4c65-b4bf-b580da26e0c5</a:MessageID>
    <a:ReplyTo>
      <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
    </a:ReplyTo>
    <a:To s:mustUnderstand="1">https://secure-ausomxana.crmondemand.com/Services/Integration</a:To>
    <o:Security xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" s:mustUnderstand="1">
      <u:Timestamp u:Id="_0">
        <u:Created>2011-05-02T13:30:09.360Z</u:Created>
        <u:Expires>2011-05-02T13:35:09.360Z</u:Expires>
      </u:Timestamp>
      <o:UsernameToken u:Id="uuid-dc3605a0-6878-42f4-b1f2-37d5c04ed7b4-2">
        <o:Username>Bob</o:Username>
        <o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">1234</o:Password>
      </o:UsernameToken>
    </o:Security>
  </s:Header>
  <s:Body>
    <t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
      <t:TokenType>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</t:TokenType>
      <t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
      <t:Entropy>
        <t:BinarySecret u:Id="uuid-7195ad74-580b-4e52-9e2c-682e5a684345-1" Type="http://schemas.xmlsoap.org/ws/2005/02/trust/Nonce">bI4xuyKwZ8OkQYBRnz2LDNV+zhIOnl0nwP24yI1QAwA=</t:BinarySecret>
      </t:Entropy>
      <t:KeySize>256</t:KeySize>
    </t:RequestSecurityToken>
  </s:Body>
</s:Envelope>

Esto parece estar muy cerca, sin embargo parece que esta cifra realmente el cuerpo del mensaje soap que es algo que NO queremos que suceda.

Si puedo especificar wsHttpBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName; con el sólo uso de SecurityMode.Transport se remonta a donde se dice que su anónimo.

¿Cuál es el obstáculo final no soy capaz de claro en esto?

Solución Final: di cuenta que había puesto esto en caso de que ayude a alguien, no es realmente muy diferente aquí, otras la UserToken objeto envuelto en un nodo de Seguridad que es lo que mi proveedor de servicio requerido y parece ser la forma de su salida de mis anteriores ejemplos de lo que yo podría obtener generado.

<system.serviceModel>
  <bindings>    
    <basicHttpBinding>
      <binding name="Contact" closeTimeout="00:01:00" openTimeout="00:01:00"
          receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
          bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
          maxBufferSize="524288" maxBufferPoolSize="524288" maxReceivedMessageSize="524288"
          messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
          useDefaultWebProxy="true">
        <readerQuotas maxDepth="32" maxStringContentLength="65536" maxArrayLength="131072"
            maxBytesPerRead="32768" maxNameTableCharCount="131072" />
        <security mode="Transport">
          <transport clientCredentialType="None" proxyCredentialType="None"
              realm="" />
          <message clientCredentialType="UserName" algorithmSuite="Default" />
        </security>
      </binding>         
    </basicHttpBinding>
  </bindings>
  <client>
    <endpoint address="https://secure-ausomxana.crmondemand.com/Services/Integration"
       binding="basicHttpBinding" bindingConfiguration="Contact"
       contract="OnDemandContactService.Contact" name="OnDemand.Contact.Endpoint">
      <headers>        
        <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
          <wsse:UsernameToken>
            <wsse:Username>USERNAME</wsse:Username>
            <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">PASSWORD</wsse:Password>
          </wsse:UsernameToken>
        </wsse:Security>
      </headers>
    </endpoint>
  </client>
</system.serviceModel>

Ver Con C#, WCF, SOAP consumidor que utiliza PSES autenticación en texto plano? de cómo configurarlo usando el código y no config

  • ¿Por qué se establece Básicas de seguridad en el transporte? ¿Necesita tanto de transporte y de autenticación de mensaje?
  • ¿Crees que se podría modificar esto para mostrar una breve receta? Es difícil hacerlo a través de la narración; no estoy muy claro en lo que son la suma y la resta como la narración continúa.
  • La versión concisa es que si esperas un mensaje para uso wsse:Security que usted necesita para utilizar la asignación estática en la web.config que tengo en mi solución final. Si necesitas variar el nombre de usuario y la contraseña, como puedo decir que estás SOL.
  • Gracias. Terminé la publicación de mi propia pregunta, y con la ayuda de los demás, aterrizamos en una forma de hacerlo: stackoverflow.com/questions/14327960/…
  • la manera de incluir la pses de seguridad en la configuración de encabezado es increíble y estaba tratando de implementar en el código que me llevó para siempre.
  • sí me di por vencido en tratar de implementarlo en el código, nunca llegué a tener éxito, pero con este bloque era una vela para la autenticación con el terrible api de soap he tenido que lidiar con.
  • esta pregunta realmente me ayudó. gracias por preguntar 🙂
  • Se tu nombre de usuario y la contraseña codificada en el config, o lo hizo de alguna manera de actualizar en tiempo de ejecución? Gran post, aunque, muy útil.
  • yo sólo he utilizado directamente en la configuración, el enlace en la parte inferior de mi pregunta puede permitir modificar las credenciales en tiempo de ejecución.
  • Viejo post, pero todavía hay personas que siguen usando JABÓN aquí… 🙁 El cliente encabezados me ayudó a solucionar mi problema. No tenía la necesidad de la extra de transporte y ajustes de los mensajes en la unión. Gracias

3 Kommentare

  1. 58

    Si usted necesita para enviar el nombre de Usuario a través de HTTPS puede utilizar el estándar de enfoque (si su WSDL está definido correctamente este debe ser creado para usted automáticamente al agregar referencia de servicio):

    <bindings>
      <basicHttpBinding>
        <binding name="secured">
          <security mode="TransportWithMessageCredential">
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint name="..." address="https://..." contract="..." binding="basicHttpBinding"
                bindingConfiguration="secured" />
    </client>

    Ar puede definir de unión en el código:

    var basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);
    basicHttpBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;

    Va a establecer credenciales en proxy como lo haces ahora:

    client.ClientCredentials.UserName.UserName = "bob";
    client.ClientCredentials.UserName.Password = "1234";

    Si sólo necesita UserNameToken perfil a través de HTTP sin ningún otro tipo de infraestructura WS-Security, el enfoque más sencillo es el uso de ClearUserNameBinding.

    Si usted necesita el mismo nombre de usuario y contraseña para todas las peticiones desde el cliente puede utilizar simple basicHttpBinding sin ningún tipo de seguridad e incluir el encabezado estática de configuración:

    <client>
      <endpoint ...>
        <headers>
          <wsse:UsernameToken xmlns:wsse='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' >
            <wsse:Username>Bob</wsse:Username>
            <wsse:Password Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText'>
               1234
            </wsse:Password>
          </wsse:UsernameToken>
        </headers>
      </endpoint>
    </client> 

    Si necesitas algo más complejo de mostrar la parte pertinente de WSDL (de aserción de seguridad) o la muestra de solicitud SOAP. También mencionar si son necesarios para utilizar HTTP o HTTPS.

    • Sí, este conector se utiliza en cada una de las peticiones sin ningún tipo de información cambiante, aparte de la obligación de enviar al UsernameToken la única otra especificación es que el servicio se accede a través de HTTPS.
    • He añadido algunos cambios en la configuración de HTTPS
    • Ladislav esto sin duda parece ser la solución, más específicamente, sólo empujar la cadena de encabezado en la definición de extremo. Agradezco su ayuda ya que este tipo de configuración no es mi fuerte. Voy a seguir con la recompensa del premio después de hablar con el proveedor de servicios me parece que se puede comunicar correctamente ahora. Sin embargo, de que su servicio es de sólo roto ahora y no mis mensajes soap.
    • Esto definitivamente era la solución, que nunca fue capaz de conseguir realmente en cualquier lugar a la configuración del nombre de usuario y contraseña a través de código, pero el uso de los encabezados elemento en la configuración lo hizo.
    • Si usted está recibiendo un MessageSecurityException, mira mi respuesta a continuación. Usted puede ser que necesite para quitar la marca de hora y establecer el tipo de contenido así.
  2. 7

    @Ladislav respuesta es correcta. Sin embargo, yo estaba un MessageSecurityException para un servicio web SOAP 1.1 yo estaba tratando de usar. Siguiente este blog de Scott Hanselman, yo era capaz de hacer que funcione. Este es el código que terminan usando:

        var oldBinding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);
        oldBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
        //remove the timestamp
        BindingElementCollection elements = oldBinding.CreateBindingElements();
        elements.Find<SecurityBindingElement>().IncludeTimestamp = false;
        //sets the content type to application/soap+xml
        elements.Find<TextMessageEncodingBindingElement>().MessageVersion = MessageVersion.Soap11;
        CustomBinding newBinding = new CustomBinding(elements);
    • La lectura a través de este blog son usted seguro de que este hecho responde a mi pregunta original? Leyendo el post parece que MessageCredentialType.UserName enviará sólo un nombre de usuario, el cual puede ser útil para una ApiKey estilo auth mientras violar la WS-normas de Seguridad. Nunca he entendido por qué la gente con las normas de uso que al instante las violan, supongo que podría ser que el WS-* las normas son tan absurdamente arcano ninguna persona razonable puede entender a seguir, aunque ellos significan demasiado. El WS-* normas SOA de nuevo la mitad de una década. «Microservices» están mucho más cerca del fin de SOA
    • En realidad, la ClientCredentialType UserName incluye tanto nombre de Usuario y Contraseña propiedades. @ladislav la respuesta que me han ayudado a conseguir en el camino correcto. Solo quería añadir un par más cambios a realizar un trabajo para el servicio web estoy llamando. He publicado esto como una respuesta porque 1) se puede ayudar a otros con el mismo problema, y 2) sé que esto debe ser un comentario debajo de su respuesta, pero el código no es el formato de bien en un comentario. Estoy de acuerdo en que el WS-* las normas son excesivamente complejos.
  3. 3

    Uso wsHttpBinding, no basicHttpBinding.

    De hecho, sólo debe utilizar «Agregar Referencia de Servicio» y seleccione el WSDL del servicio.

    • No estoy de control de la estación y la estación probable que viole alguna serie de las infinitas permutaciones de la absurda PSES «normas».
    • Wow, utilizando WSHttpBinding en lugar de BasicHttpBinding envía un cargamento de encabezados adicionales (WS-Addressing, la Acción, la Confianza, etc.) además de la Seguridad. Mi petición se ha duplicado en tamaño. No, gracias a eso. Pero «Agregar Referencia de Servicio» es un buen consejo.
    • ¿su servicio de uso PSES de seguridad? Esta pregunta es acerca de PSES.
    • Sí, utiliza PSES seguridad de la contraseña (sólo).
    • entonces no veo la forma en que se trabaja con basicHttpBinding.
    • De alguna manera la configuración de ClientCredentialType = BasicHttpMessageCredentialType.UserName envía la debida encabezado de WS-Security.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Recent Articles

Python «set» con duplicados/elementos repetidos

Hay una forma estándar de representar un "conjunto" que puede contener elementos duplicados. Como yo lo entiendo, un conjunto tiene exactamente un cero o...

Python: generador de expresión vs rendimiento

En Python, ¿hay alguna diferencia entre la creación de un generador de objetos a través de un generador de expresión versus el uso de...

Cómo exportar/importar la Masilla lista de sesiones?

Hay una manera de hacer esto? O tengo que tomar manualmente cada archivo de Registro? InformationsquelleAutor s.webbandit | 2012-10-23

no distingue mayúsculas de minúsculas coincidentes en xpath?

Por ejemplo, para el xml a continuación <CATALOG> <CD title="Empire Burlesque"/> <CD title="empire burlesque"/> <CD...