2012-04-18 15 views
7

Estoy teniendo que volver a escribir una API REST existente utilizando .NET (escrito originalmente con Ruby). Desde la perspectiva del cliente, tiene que funcionar exactamente de la misma manera que la antigua API, es decir, el código del cliente no debe cambiar. La API actual requiere autenticación básica. Así que para llamar a la API de edad, el siguiente funciona perfectamente: -ASP.Net Web API - Cabecera de autorización en blanco

 var wc = new System.Net.WebClient(); 
     var myCache = new CredentialCache(); 
     myCache.Add(new Uri(url), "Basic", new NetworkCredential("XXX", "XXX")); 
     wc.Credentials = myCache; 
     var returnBytes = wc.DownloadData("http://xxxx"); 

(he tenido que ommit la verdadera URL/nombre de usuario etc/contraseña por razones de seguridad).

Ahora estoy escribiendo la nueva API usando ASP.Net Web API con MVC4. Tengo un problema extraño y no puedo encontrar a nadie más con exactamente el mismo problema. Con el fin de apoyar la autenticación básica, he seguido las directrices aquí:

http://sixgun.wordpress.com/2012/02/29/asp-net-web-api-basic-authentication/

Una cosa, pongo el código para "gancho en el controlador" en el archivo Global.asax.cs en el Application_Start() evento (que no fue explicado, así que supuse).

De todos modos, si llamo a mi API (que he implementado en IIS) utilizando el código anterior, el encabezado Authorization siempre es nulo, y lo anterior falla con 401 desautorizado. Sin embargo, si configuro manualmente el encabezado con este código, funciona bien, es decir, el encabezado Authorization ahora existe y puedo autenticar al usuario.

private void SetBasicAuthHeader(WebClient request, String userName, String userPassword) 
    { 
     string authInfo = userName + ":" + userPassword; 
     authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo)); 
     request.Headers["Authorization"] = "Basic " + authInfo; 
    } 
    ....... 
    var wc = new System.Net.WebClient(); 
    SetBasicAuthHeader(request, "XXXX", "XXXX"); 
    var returnBytes = wc.DownloadData("http://xxxx"); 

A pesar de que las obras, que no es bueno para mí, porque los usuarios existentes de la API existente no se van a configurar manualmente la cabecera.

Al leer acerca de cómo funciona la Autenticación básica, la solicitud inicial es anónima, luego se devuelve al cliente 401, y luego el cliente intenta volver a intentarlo. Sin embargo, si pongo un punto de quiebre en mi código, nunca volverá a golpear el código en el ejemplo de Antony. Esperaba que mi punto de quiebre fuera golpeado dos veces.

¿Alguna idea de cómo puedo hacer que esto funcione?

Respuesta

9

Estás esperando el comportamiento correcto. System.Net.WebClient no incluye automáticamente los encabezados de Autorización en la solicitud inicial. Solo los envía cuando se los desafía adecuadamente con una respuesta, que a mi conocimiento es un código de estado 401 y un encabezado WWW-Authenticate correcto. Consulte here y here para obtener más información.

Supongo que su controlador de autenticación básica no devuelve el encabezado WWW-Authenticate y, como tal, WebClient nunca intenta enviar las credenciales en una segunda solicitud. Deberías poder ver esto en Fiddler o una herramienta similar.

Si su manejador hizo algo como esto, usted debe presenciar el enfoque de cliente Web de trabajo:

//if is not authenticated or Authorization header is null 
return base.SendAsync(request, cancellationToken).ContinueWith(task => 
    { 
     var response = task.Result; 
     response.StatusCode = HttpStatusCode.Unauthorized; 
     response.Headers.Add("WWW-Authenticate", "Basic realm=\"www.whatever.com\""); 
     return response; 
    }); 

//else (is authenticated) 
return base.SendAsync(request, cancellationToken); 

Como habrá notado, si se incluyen las cabeceras de autorización en cada solicitud (como lo hizo en su enfoque alternativo), entonces su controlador ya funciona como está. Por lo tanto, puede ser suficiente, simplemente no es para WebClient y otros clientes que operan de la misma manera.

+0

Perfecto - funcionó! Muchas gracias. – nickthompson

Cuestiones relacionadas