Error en el cliente WCF que consume el servicio web Axis 2 con WS-Security UsernameToken PasswordDigest authentication scheme

Tengo un cliente WCF que se conecta a un servicio web Axis2 basado en Java (fuera de mi control). Está a punto de aplicar WS-Security y necesito arreglar el cliente .NET. Sin embargo, estoy luchando por proporcionar la autenticación correcta. Soy consciente de que WSE 3.0 podría hacerlo más fácil, pero preferiría no volver a una tecnología obsoleta.

Cuestiones similares (no resueltas) incluyen esto , esto y esto .

El mensaje SOAP debe verse así:

    2010-05-28T12:50:33.675+01:00  

Sin embargo, el mío se ve así:

     2010-06-23T10:31:23.441Z 2010-06-23T10:36:23.441Z            

Mi cliente se ve así: PD Tenga en cuenta el param de SecurityHeaderType requerido . ¿Que es eso?

 public MyAck SendRequest(MyRequest request) { RemoteServicePortTypeClient client = new RemoteServicePortTypeClient(); client.ClientCredentials.UserName.UserName = "JAY"; client.ClientCredentials.UserName.Password = "AND"; // what is the difference between the two different Credential types?? //client.ClientCredentials.HttpDigest.ClientCredential.UserName = "SILENT"; //client.ClientCredentials.HttpDigest.ClientCredential.Password = "BOB"; SecurityHeaderType sht = new SecurityHeaderType(); //sht.Any = ???; // How do I use this??? //sht.AnyAttr = ???; // How do I use this ??? // SecurityHeaderType is a required parameter return client.RemoteServiceOperation_Provider(sht, request); } 

La vinculación actual es la siguiente:

         

También probé un enlace personalizado y obtuve un error similar:

        

Y punto final (La dirección obviamente cambió …):

  

El error personalizado que se devuelve es el siguiente:

 0 UNEXPECTED  2010-06-23T13:28:54Z 

He leído mucho sobre encabezados personalizados, tokens, enlaces y mi cerebro está completamente confundido. ¿Alguien puede sugerir un proceso paso a paso para enviar el mensaje en el formato correcto?

Este parece ser el camino a seguir para WCF, utilizando tokens personalizados, pero ¿cómo se debe aplicar el resumen y el nonce según sea necesario?

Cualquier ayuda bienvenida.

ACTUALIZAR

He tenido un éxito limitado. He utilizado la biblioteca Microsoft.Web.Services3 para crear un UsernameToken con el resumen correcto. Luego creé mi propio comportamiento personalizado y en el método BeforeSendRequest hice lo siguiente para inyectar el encabezado:

 object IClientMessageInspector.BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel) { UsernameToken ut = new UsernameToken("USERNAME", "PASSWORD", PasswordOption.SendHashed); XmlElement securityElement = ut.GetXml(new XmlDocument()); MessageHeader myHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", securityElement, false); request.Headers.Add(myHeader); return Convert.DBNull; } 

Agrego el comportamiento de esta manera:

 CustomBehavior behavior = new CustomBehavior("USERNAME", "PASSWORD"); client.Endpoint.Behaviors.Add(behavior); 

Ahora puedo ver los encabezados al otro lado:

             2010-06-24T16:23:58Z    

Pero estoy obteniendo el error:

  soapenv:Server WSDoAllReceiver: security processing failed; nested exception is: org.apache.ws.security.WSSecurityException: General security error (WSSecurityEngine: Callback supplied no password for: USERNAME) urn:Remote_Provider   0 UNEXPECTED  2010-06-24T17:23:59Z    

Parece que falta un atributo Tipo en el nodo de contraseña:

 Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest" 

Sin embargo, no estoy seguro de si las configuraciones de seguimiento de seguridad y registro están eliminando los atributos y el contenido de esos nodos. Intenté utilizar la configuración logKnownPii en el registro de diagnósticos, pero la información de seguridad permanece oculta. Alguna idea sobre eso?

Puedo confirmar que la ACTUALIZACIÓN de mi pregunta realmente funciona:

 object IClientMessageInspector.BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel) { UsernameToken ut = new UsernameToken("USERNAME", "PASSWORD", PasswordOption.SendHashed); XmlElement securityElement = ut.GetXml(new XmlDocument()); MessageHeader myHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", securityElement, false); request.Headers.Add(myHeader); return Convert.DBNull; } 

Y el cliente:

 CustomBehavior behavior = new CustomBehavior("USERNAME", "PASSWORD"); client.Endpoint.Behaviors.Add(behavior); 

El mensaje de error no estaba relacionado. El encabezado de seguridad funciona con un basicHttpBinding muy simple:

      

La muestra del código de esto en acción se puede encontrar en mi blog: http://benpowell.org/supporting-the-ws-i-basic-profile-password-digest-in-a-wcf-client-proxy/

Esta pregunta está bien escrita, muchas gracias. En referencia al comentario “¿Cómo uso esto?” De @ Junto, resulta que se puede usar el parámetro SecurityHeader en el método de servicio para agregar el encabezado. He incluido un ejemplo a continuación. Creo que lo que está sucediendo es que la herramienta SvcUtil.exe está vomitando cuando intenta leer las DTD WS *. Esto no es obvio cuando utiliza el asistente “Agregar referencia de servicio”. Pero es muy obvio cuando ejecuta svcutil.exe desde la línea de comando. Debido a que svcutil.exe no puede leer las DTD WS *, el objeto SecurityHeader no está bien desarrollado. Pero Microsoft te da una salida con la propiedad .Any. Puede serializar la clase UsernameToken directamente en. Cualquier propiedad y su encabezado se agregará al mensaje. De nuevo, gracias por esta excelente pregunta.

Cómo usar el parámetro SecurityHeader para agregar un encabezado de seguridad UsernameToken:

Herramientas requeridas:

Fiddler2 (o similar): realmente no puede resolver nada de esto sin inspeccionar los encabezados http.

Referencia requerida:

 Microsoft.Web.Services3.dll -- you can reference this 2.0 framework assembly from your 4.0 assembly 

Llamada de servicio WCF:

 // Initialization of the service... _service = new MyService("MyEndpoint", RemoteUri); // etc. // Calling the service -- note call to GetSecurityHeader() _service.ServiceAction(GetSecurityHeader(), "myParam1"); // etc. ///  /// Construct the WSE 3.0 Security Header ///  private SecurityHeader GetSecurityHeader() { SecurityHeader h = new SecurityHeader(); UsernameToken t = new UsernameToken(RemoteLogin, RemotePassword, PasswordOption.SendPlainText); h.Any = new XmlElement[1]; h.Any[0] = t.GetXml(new XmlDocument()); return h; } 

App.config:

                  

Recientemente tuve un problema similar y dejé de buscar una solución que no sea de WSE. Después de un par de días de sacarme el pelo, terminé la descarga del WSE 3.0 SDK, generando una clase de proxy usando WseWsdl3.exe y creando una nueva política para UsernameToken. Estaba funcionando en 15 minutos. Lo siguiente actualmente está trabajando para mí.

 RemoteService service = new RemoteService(); //generated class UsernameToken token = new UsernameToken(username, password, PasswordOption.SendPlainText); Policy policy = new Policy(); policy.Assertions.Add(new UsernameOverTransportAssertion()); service.SetClientCredential(token); service.SetPolicy(policy); var result = service.MethodCall(); 
    Intereting Posts