Desafortunadamente, he determinado (mediante el análisis del código fuente de referencia WCF y la ayuda de la herramienta Fiddler para la detección de sesión HTTP) que esto es un error en la pila WCF.
Utilizando Fiddler, noté que mi servicio WCF se comportaba de manera diferente a cualquier otro sitio web que utiliza autenticación básica.
Para ser claros, esto es lo que debería ocurrir:
- navegador envía
GET
solicitud sin el conocimiento de que una contraseña es incluso necesario.
- El servidor web rechaza la solicitud con un estado
401 Unauthorized
e incluye un encabezado WWW-Authenticate
que contiene información sobre métodos de autenticación aceptables.
- El navegador solicita al usuario que ingrese las credenciales.
- El navegador reenvía
GET
solicitud e incluye el encabezado Authentication
apropiado con las credenciales.
- Si las credenciales fueron correctas, el servidor web responde con
200 OK
y la página web. Si las credenciales fueron incorrectas, el servidor web responde con 401 Unauthorized
e incluye el mismo encabezado WWW-Authenticate
que el paso 2.
lo que realmente estaba sucediendo con mi servicio WCF fue la siguiente:
- navegador envía
GET
solicitud sin el conocimiento de que una contraseña es incluso necesario.
- WCF nota que no hay un encabezado
Authentication
en la solicitud y rechaza ciegamente la solicitud con un estado 401 Unauthorized
e incluye un encabezado WWW-Authenticate
. Todo normal hasta ahora.
- El navegador solicita credenciales al usuario. Aún normal.
- El navegador reenvía
GET
solicitud que incluye el encabezado Authentication
apropiado.
- Si las credenciales fueron correctas, el servidor web responde con
200 OK
. Todo está bien. Si las credenciales fueron incorrectas, WCF responde con 403 Forbidden
y no incluye ningún encabezado adicional como WWW-Authenticate
.
Cuando el navegador obtiene el estado 403 Forbidden
, no percibe que se trata de un intento de autenticación fallido. Este código de estado está destinado a informar al navegador que la URL a la que intentó acceder no está permitida. No se relaciona con la autenticación de ninguna manera. Esto tiene el efecto secundario terrible de que cuando el usuario escribe su nombre de usuario/contraseña incorrectamente (y el servidor rechaza con 403), entonces el navegador web no reprompe al usuario para que escriba sus credenciales nuevamente. De hecho, el navegador web cree que la autenticación ha tenido éxito y almacena esas credenciales para el resto de la sesión.
Con esto en mente, me pidió aclaraciones:
La RFC 2617 (http://www.faqs.org/rfcs/rfc2617.html#ixzz0eboUfnrl) no se menciona en ninguna parte la utilización del código de estado 403 Forbidden
. De hecho, lo que realmente tiene que decir al respecto es la siguiente:
Si el servidor de origen no desea aceptar las credenciales enviadas con una solicitud , es conveniente devolver una respuesta 401 (no autorizado) . La respuesta DEBE incluir un encabezado WWW-Authenticate que contenga al menos un desafío (posiblemente nuevo) aplicable a el recurso solicitado.
WCF no hace ninguno de estos. Tampoco envía correctamente un código de estado 401 Unauthorized
. Tampoco incluye un encabezado WWW-Authenticate
.
ahora para encontrar el cuerpo del delito dentro del código fuente de WCF:
descubrí que en la clase HttpRequestContext
es un método llamado ProcessAuthentication
, que contiene lo siguiente (extracto):
if (!authenticationSucceeded)
{
SendResponseAndClose(HttpStatusCode.Forbidden);
}
defiendo Microsoft en muchas cosas, pero esto es indefendible.
Afortunadamente, lo tengo trabajando a un nivel "aceptable". Simplemente significa que si el usuario ingresa accidentalmente su nombre de usuario/contraseña incorrectamente, entonces la única forma de obtener otro intento es cerrar completamente su navegador web y reiniciarlo para volver a intentarlo.Todo porque WCF es no que responde al intento de autenticación fallido con un encabezado 401 Unauthorized
y WWW-Authenticate
según la especificación.
Es hora de cambiar a un marco de http real como openrasta :) – SerialSeb
@serialseb No tuve el coraje de decirle que renuncié a tratar de resolver problemas de autenticación en WCF y fui directamente a HttpListener directamente. –
Saludos chicos :) Darrel, vi tus comentarios en otra discusión y créanme lo he considerado como una opción. Afortunadamente, aún no hemos invertido demasiado en WCF REST. Entonces podemos seguir adelante y abandonarlo. – nbevans