2009-05-22 95 views
40

Estoy intentando escribir un cliente de servicio web en C# cuyo servicio web es Java Axis 1.4. El servicio Axis requiere la autorización : Valor básico básico del encabezado Base64EncodedToken en los encabezados HTTP. No puedo encontrar una manera de establecer este encabezado en formas estándar de consumir servicios web en visual studio.net, como referencia normal generada por WSDL ni con WSE3.0Cómo agregar un encabezado Http personalizado para el servicio web C# Cliente que consume el servicio web Axis 1.4

No puedo usar WCF porque el proyecto está desarrollado usando .net 2.0.

¿Hay alguna manera de hacer esto?

Respuesta

7

Si desea enviar una costumbre encabezado HTTP (no un encabezado SOAP), entonces tienes que utilizar la clase HttpWebRequest el código se vería así:

HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url); 
webRequest.Headers.Add("Authorization", token); 

No se pueden añadir cabeceras HTTP utilizando el estudio visual generada proxy, que puede ser un verdadero dolor.

+0

"no puede añadir cabeceras HTTP utilizando el estudio visual proxy generado" ¿sigue siendo el caso? – chaostheory

+0

Puedo agregar encabezados como este, pero ¿cómo los vuelvo a obtener en el Servicio WCF? – Joshy

24

¿Estamos hablando de WCF aquí? Tuve problemas en los que las llamadas de servicio no agregaban los encabezados de autorizaciones HTTP, y el hecho de incluir cualquier llamada en esta declaración solucionó mi problema.

using (OperationContextScope scope = new OperationContextScope(RefundClient.InnerChannel)) 
    { 
      var httpRequestProperty = new HttpRequestMessageProperty(); 
      httpRequestProperty.Headers[System.Net.HttpRequestHeader.Authorization] = "Basic " + 
      Convert.ToBase64String(Encoding.ASCII.GetBytes(RefundClient.ClientCredentials.UserName.UserName + ":" + 
      RefundClient.ClientCredentials.UserName.Password)); 
      OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty; 

      PaymentResponse = RefundClient.Payment(PaymentRequest); 
    } 

Este fue corriendo llamadas SOAP a través de ESB IBM .NET con autenticación básica sobre HTTP o HTTPS.

Espero que esto ayude a alguien porque tuve grandes problemas para encontrar una solución en línea.

+2

Este fue en realidad mi problema. De alguna manera, cuando configura las credenciales en el proxy, no funciona. ¡Gracias! – Tawani

+0

Estoy usando WCF/Soap, así que esto funcionó muy bien para mí. En mi caso, necesitaba un encabezado personalizado llamado "Auth-Token". Entonces mi código (VB.NET) era -> httpRequestProperty.Headers.Add ("Auth-Token", "xxxxx") – robnick

+0

Esto también solucionó mis problemas. Tuve el mismo problema que Tawani, cuando establecí las credenciales a través del proxy volví a 401. ¡Pero con tu código todo funciona a la perfección! ¡Muchas gracias! – merger

40

Parece que el autor original ha encontrado su solución, pero para cualquier otra persona que se ve aquí en busca de agregar encabezados personalizados reales, si tiene acceso a mod el código de protocolo generada se puede anular GetWebRequest:

protected override System.Net.WebRequest GetWebRequest(Uri uri) 
{ 
    System.Net.WebRequest request = base.GetWebRequest(uri); 
    request.Headers.Add("myheader", "myheader_value"); 
    return request; 
} 

Asegúrese de eliminar el atributo DebuggerStepThroughAttribute si desea entrar en él.

+0

Esto era exactamente lo que necesitaba. El Servicio web devolvía 500 en lugar de 401 para No autorizado, por lo que las credenciales nunca se enviaron utilizando el enfoque en la respuesta aceptada. Aunque me siento sucio modificando el código generado, esto me permitió obligar a enviarlos con la primera solicitud. Ver http://www.west-wind.com/weblog/posts/243915.aspx. –

+2

Oye, eso parece exactamente lo que necesito. pero ¿dónde debería poner esta función? –

+0

, pero ¿no puede una adición de encabezado tener múltiples valores separados por comas en la porción de valor para el encabezado que está agregando? Eso también es muy importante saberlo, como para los parámetros de Autorización OAuth – PositiveGuy

4

Encuentro este código y resuelvo mi problema.

http://arcware.net/setting-http-header-authorization-for-web-services/

protected override WebRequest GetWebRequest(Uri uri) 
{ 
    // Assuming authValue is set from somewhere, such as the config file 
    HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(uri); 
    request.Headers.Add("Authorization", string.Format("Basic {0}", authValue)); 
    return request; 
} 
+2

Oye, eso parece exactamente lo que necesito. pero ¿dónde debería poner esta función? –

+1

También no sé dónde ponerlo y estoy usando .net 4.0. Mi servicio se genera de forma diferente a otros ejemplos que encuentro –

0

Esto es lo que funcionó para mí:

protected override System.Net.WebRequest GetWebRequest(Uri uri) 
{ 
     HttpWebRequest request; 
     request = (HttpWebRequest)base.GetWebRequest(uri); 
     NetworkCredential networkCredentials = 
     Credentials.GetCredential(uri, "Basic"); 
     if (networkCredentials != null) 
     { 
      byte[] credentialBuffer = new UTF8Encoding().GetBytes(
      networkCredentials.UserName + ":" + 
      networkCredentials.Password); 
      request.Headers["Authorization"] = 
      "Basic " + Convert.ToBase64String(credentialBuffer); 
      request.Headers["Cookie"] = "BCSI-CS-2rtyueru7546356=1"; 
      request.Headers["Cookie2"] = "$Version=1"; 
     } 
     else 
     { 
      throw new ApplicationException("No network credentials"); 
     } 
     return request; 
} 

No se olvide de establecer esta propiedad:

service.Credentials = new NetworkCredential("username", "password"); 

la galleta y la Cookie2 se establecen en la cabecera porque el servicio de Java no aceptaba la solicitud y recibí un error no autorizado.

+0

Me deshice de la sobrecarga anterior y solo este código hizo toda la magia: serviceClient.CookieContainer = new CookieContainer(); –

3

En lugar de modding el código generado automáticamente o envolviendo cada llamada en código duplicado, se puede inyectar cabeceras HTTP personalizados mediante la adición de un inspector de mensaje personalizado, es más fácil de lo que parece:

public class CustomMessageInspector : IClientMessageInspector 
{ 
    readonly string _authToken; 

    public CustomMessageInspector(string authToken) 
    { 
     _authToken = authToken; 
    } 

    public object BeforeSendRequest(ref Message request, IClientChannel channel) 
    { 
     var reqMsgProperty = new HttpRequestMessageProperty(); 
     reqMsgProperty.Headers.Add("Auth-Token", _authToken); 
     request.Properties[HttpRequestMessageProperty.Name] = reqMsgProperty; 
     return null; 
    } 

    public void AfterReceiveReply(ref Message reply, object correlationState) 
    { } 
} 


public class CustomAuthenticationBehaviour : IEndpointBehavior 
{ 
    readonly string _authToken; 

    public CustomAuthenticationBehaviour (string authToken) 
    { 
     _authToken = authToken; 
    } 
    public void Validate(ServiceEndpoint endpoint) 
    { } 

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) 
    { } 

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) 
    { } 

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) 
    { 
     clientRuntime.ClientMessageInspectors.Add(new CustomMessageInspector(_authToken)); 
    } 
} 

Y cuando instanciar su clase de cliente simplemente puede añadirlo como un comportamiento:

this.Endpoint.EndpointBehaviors.Add(new CustomAuthenticationBehaviour("Auth Token")); 

Esto hará que cada llamada de servicio de salida para que su encabezado HTTP personalizado.

+1

Saeb Amini, gracias. Esta fue la respuesta que estaba buscando para resolver mi problema utilizando un servicio web de terceros que había cambiado a autenticación de dos factores. Su API nos fue proporcionada por XSDs y WSDLs que generamos el código del cliente a través del programa svcutil. Usar el código anterior me permitió agregar el comportamiento para inyectar el encabezado HTTP con el token para hacer la autenticación de 2 factores. ¡Gracias de nuevo! – bolski

1

La respuesta de user334291 fue un salvavidas para mí. Sólo quiero añadir cómo puede agregar lo que el PO originalmente destinado a hacer (lo que terminé usando):

Anulación de la función GetWebRequest en el código de servicio web generado:

protected override System.Net.WebRequest GetWebRequest(Uri uri) 
{ 
    System.Net.WebRequest request = base.GetWebRequest(uri);   
    string auth = "Basic " + Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(this.Credentials.GetCredential(uri, "Basic").UserName + ":" + this.Credentials.GetCredential(uri, "Basic").Password)); 
    request.Headers.Add("Authorization", auth); 
    return request; 
} 

y establecer las credenciales antes de llamar el servicio web:

client.Credentials = new NetworkCredential(user, password);  
Cuestiones relacionadas