2012-04-09 16 views
18

Estoy tratando de usar un HttpClient para un servicio de terceros que requiera autenticación HTTP básica. Estoy usando el AuthenticationHeaderValue. Aquí es lo que he encontrado hasta el momento:El encabezado de autenticación HttpClient no se envía

HttpRequestMessage<RequestType> request = 
    new HttpRequestMessage<RequestType>(
     new RequestType("third-party-vendor-action"), 
     MediaTypeHeaderValue.Parse("application/xml")); 
request.Headers.Authorization = new AuthenticationHeaderValue(
    "Basic", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(
     string.Format("{0}:{1}", "username", "password")))); 

var task = client.PostAsync(Uri, request.Content); 
ResponseType response = task.ContinueWith(
    t => 
    { 
     return t.Result.Content.ReadAsAsync<ResponseType>(); 
    }).Unwrap().Result; 

Parece que la acción POST funciona bien, pero yo no regreso los datos que espero. A través de un proceso de prueba y error, y finalmente usando Fiddler para olfatear el tráfico sin procesar, descubrí que el encabezado de la autorización no se está enviando.

He visto this, pero creo que tengo el esquema de autenticación especificado como parte del constructor AuthenticationHeaderValue.

¿Hay algo que me he perdido?

Respuesta

25

Su código es el que debería funcionar - Recuerdo corriendo en un problema similar establecer los encabezados de autorización y que resuelve haciendo un Headers.Add() en lugar de establecer que:

request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "username", "password")))); 

ACTUALIZACIÓN: Se ve como cuando haces una solicitud. Contenido, no todos los encabezados se reflejan en el objeto de contenido. Puede ver esto inspeccionando la solicitud. Hderes frente a request.Content.Headers. Una cosa que quizás quieras probar es usar SendAsync en lugar de PostAsync. Por ejemplo: el establecimiento de

HttpRequestMessage<RequestType> request = 
    new HttpRequestMessage<RequestType>(
     new RequestType("third-party-vendor-action"), 
     MediaTypeHeaderValue.Parse("application/xml")); 

request.Headers.Authorization = 
    new AuthenticationHeaderValue(
     "Basic", 
     Convert.ToBase64String(
      System.Text.ASCIIEncoding.ASCII.GetBytes(
       string.Format("{0}:{1}", "username", "password")))); 

request.Method = HttpMethod.Post; 
request.RequestUri = Uri; 
var task = client.SendAsync(request); 

ResponseType response = task.ContinueWith(
    t => 
     { return t.Result.Content.ReadAsAsync<ResponseType>(); }) 
     .Unwrap().Result; 
+0

he intentado eso y algo similar con 'request.Headers.Authorization' con los mismos resultados. Me ha dejado un poco de scratch, ya que no estoy seguro de qué probar después. Sé que la versión preliminar MVC4 beta y 4.5 son directamente incompatibles para algunas cosas. Me pregunto si eso tiene algo que ver con eso. – Ross

+0

Su actualización al menos parece enviar el encabezado de autorización. Todavía no puedo recuperar datos del servicio de terceros (probablemente haya pasado algo diferente en el cuerpo de la solicitud que me he perdido), pero al menos los encabezados correctos están pasando por alto. Es un comienzo. ¡Gracias! – Ross

+0

ASCII o UTF-8? Ver http://stackoverflow.com/questions/11743160/how-do-i-encode-and-decode-a-base64-string. – Philippe

17

Probar la cabecera en el cliente:

DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(String.Format("{0}:{1}", userName, password)))); 

Esto funciona para mí.

+1

Esto probablemente funcionaría, pero establecería los encabezados de autorización para todas las solicitudes, ¿no es así? Eso no es deseable. – Ross

+2

Para todas las solicitudes realizadas con esa instancia de un cliente, sí. ¿Está utilizando el mismo cliente para acceder a puntos finales con diferentes esquemas de autenticación? Es decir, ¿está configurando BaseAddress en la instancia del cliente o no? –

15

Esto también funcionaría y no tendría que hacer frente a las conversiones de series base 64:

var handler = new HttpClientHandler(); 
handler.Credentials = new System.Net.NetworkCredential("username", "password"); 
var client = new HttpClient(handler); 
... 
+0

solución mucho más limpia que la codificación de la combinación UID: PWD. –

2

En realidad el problema es con PostAsync - deberá utilizar SendAsync. En su código, client.PostAsync(Uri, request.Content); envía solo el contenido que los encabezados de los mensajes de solicitud no están incluidos. La forma correcta es:

HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, url) 
{ 
    Content = content 
}; 
message.Headers.Authorization = new AuthenticationHeaderValue("Basic", credentials); 
httpClient.SendAsync(message); 
+0

Mil veces gracias. He pasado horas intentando adjuntar encabezados al HttpClient y usando GetAsync y PostAsync, etc., y en general encuentro un problema para WebAPI (¡dame ServiceStack!) –

Cuestiones relacionadas