Pregunta

Mi aplicación web tiene una página de inicio de sesión que envía credenciales de autenticación mediante una llamada AJAX.Si el usuario ingresa el nombre de usuario y contraseña correctos, todo está bien, pero si no, sucede lo siguiente:

  1. El servidor web determina que, aunque la solicitud incluía un encabezado de Autorización bien formado, las credenciales en el encabezado no se autentican correctamente.
  2. El servidor web devuelve un código de estado 401 e incluye uno o más encabezados WWW-Authenticate que enumeran los tipos de autenticación admitidos.
  3. El navegador detecta que la respuesta a mi llamada al objeto XMLHttpRequest es 401 y la respuesta incluye encabezados WWW-Authenticate.Luego aparece un cuadro de diálogo de autenticación que solicita, nuevamente, el nombre de usuario y la contraseña.

Todo esto está bien hasta el paso 3.No quiero que aparezca el cuadro de diálogo, quiero manejar la respuesta 401 en mi función de devolución de llamada AJAX.(Por ejemplo, mostrando un mensaje de error en la página de inicio de sesión). Quiero que el usuario vuelva a ingresar su nombre de usuario y contraseña, por supuesto, pero quiero que vean mi formulario de inicio de sesión amigable y tranquilizador, no el feo y predeterminado del navegador. diálogo de autenticación.

Por cierto, no tengo control sobre el servidor, por lo que devolver un código de estado personalizado (es decir, algo que no sea 401) no es una opción.

¿Hay alguna manera de suprimir el cuadro de diálogo de autenticación?En particular, ¿puedo suprimir el cuadro de diálogo Autenticación requerida en Firefox 2 o posterior?¿Hay alguna forma de suprimir la conexión Conectarse a [anfitrión] ¿Diálogo en IE 6 y posterior?


Editar
Información adicional del autor (septiembre).18):
Debo agregar que el verdadero problema con el cuadro de diálogo de autenticación emergente del navegador es que no brinda información suficiente al usuario.

El usuario acaba de ingresar un nombre de usuario y contraseña a través del formulario en la página de inicio de sesión, cree que los ha escrito correctamente y ha hecho clic en el botón Enviar o presionó Enter.Su expectativa es que lo llevarán a la página siguiente o tal vez le digan que ingresó su información incorrectamente y que debe intentarlo nuevamente.Sin embargo, se le presenta un cuadro de diálogo inesperado.

El diálogo no reconoce el hecho de que él simplemente hizo Introduzca un nombre de usuario y contraseña.No indica claramente que hubo un problema y que debería intentarlo de nuevo.En cambio, el cuadro de diálogo presenta al usuario información críptica como "El sitio dice:'[reino]'." Dónde [reino] es un nombre de dominio corto que sólo le encantaría a un programador.

Los diseñadores de navegadores web toman nota:Nadie preguntaría cómo suprimir el cuadro de diálogo de autenticación si el cuadro de diálogo en sí fuera simplemente más fácil de usar.El completo La razón por la que estoy creando un formulario de inicio de sesión es que nuestro equipo de administración de productos considera, con razón, que los cuadros de diálogo de autenticación de los navegadores son horribles.

¿Fue útil?

Solución

No creo que esto sea posible: si utiliza la implementación del cliente HTTP del navegador, siempre aparecerá ese cuadro de diálogo.Me vienen a la mente dos trucos:

  1. Tal vez Flash maneje esto de manera diferente (no lo he probado todavía), por lo que tener una película flash para realizar la solicitud podría ayudar.

  2. Puedes configurar un 'proxie' para el servicio al que estás accediendo en tu propio servidor y hacer que modifique un poco los encabezados de autenticación, para que el navegador no los reconozca.

Otros consejos

Encontré el mismo problema aquí y el ingeniero de backend de mi empresa implementó un comportamiento que aparentemente se considera una buena práctica:cuando una llamada a una URL devuelve un 401, si el cliente ha configurado el encabezado X-Requested-With: XMLHttpRequest, el servidor descarta el www-authenticate encabezado en su respuesta.

El efecto secundario es que la ventana emergente de autenticación predeterminada no aparece.

Asegúrese de que su llamada API tenga la X-Requested-With encabezado establecido en XMLHttpRequest.Si es así, no hay nada que hacer excepto cambiar el comportamiento del servidor de acuerdo con esta buena práctica...

El navegador muestra un mensaje emergente de inicio de sesión cuando se cumplen las dos condiciones siguientes:

  1. El estado HTTP es 4xx
  2. WWW-Authenticate El encabezado está presente en la respuesta.

Si puede controlar la respuesta HTTP, puede eliminar el WWW-Authenticate encabezado de la respuesta y el navegador no mostrará el cuadro de diálogo de inicio de sesión.

Si no puede controlar la respuesta, puede configurar un proxy para filtrar la respuesta. WWW-Authenticate encabezado de la respuesta.

Hasta donde yo sé (no dudes en corregirme si me equivoco), no hay forma de evitar que aparezca el mensaje de inicio de sesión una vez que el navegador recibe el mensaje. WWW-Authenticate encabezamiento.

Me doy cuenta de que esta pregunta y sus respuestas son muy antiguas.Pero terminé aquí.Quizás otros también lo hagan.

Si tiene acceso al código del servicio web que devuelve el 401.Simplemente cambie el servicio para devolver un 403 (Prohibido) en esta situación en lugar de 401.El navegador no solicitará credenciales en respuesta a un 403.403 es el código correcto para un usuario autenticado que no está autorizado para un recurso específico.Cual parece ser la situación del OP.

Del documento del IETF sobre 403:

Un servidor que recibe credenciales válidas que no son adecuadas para obtener acceso que debe responder con el código de estado 403 (prohibido)

En Mozilla puedes lograrlo con el siguiente script cuando creas el objeto XMLHttpRequest:

xmlHttp=new XMLHttpRequest();
xmlHttp.mozBackgroundRequest = true;
xmlHttp.open("GET",URL,true,USERNAME,PASSWORD);
xmlHttp.send(null);

La segunda línea impide que aparezca el cuadro de diálogo....

¿Qué tecnología de servidor utiliza? ¿Existe algún producto en particular que utilice para la autenticación?

Dado que el navegador sólo hace su trabajo, creo que hay que cambiar cosas en el lado del servidor para no devolver un código de estado 401.Esto se podría hacer utilizando formularios de autenticación personalizados que simplemente devuelven el formulario nuevamente cuando falla la autenticación.

En Mozilla, configurar el parámetro mozBackgroundRequest de XMLHttpRequest (documentos) a verdadero suprime esos diálogos y hace que las solicitudes simplemente fallen.Sin embargo, no sé qué tan buena es la compatibilidad con varios navegadores (incluso si la calidad de la información de error en esas solicitudes fallidas es muy buena en todos los navegadores).

jan.vdbergh tiene la verdad: si puede cambiar el 401 en el lado del servidor por otro código de estado, el navegador no detectará ni pintará la ventana emergente.Otra solución podría ser cambiar el encabezado WWW-Authenticate por otro encabezado personalizado.No creo por qué los diferentes navegadores no lo admiten, en algunas versiones de Firefox podemos realizar la solicitud xhr con mozBackgroundRequest, pero ¿en los otros navegadores?aquí hay una interesante enlace con este problema en Chromium.

Tengo el mismo problema con MVC 5 y VPN, donde cada vez que estamos fuera de la DMZ usando la VPN, tenemos que responder este mensaje del navegador.Usando .net simplemente manejo la ruta del error usando

<customErrors defaultRedirect="~/Error"  >
  <error statusCode="401" redirect="~/Index"/>
</customErrors>

Hasta ahora ha funcionado porque la acción Índice bajo el controlador doméstico valida al usuario.La vista en esta acción, si el inicio de sesión no se realiza correctamente, tiene controles de inicio de sesión que utilizo para iniciar la sesión del usuario mediante la consulta LDAP pasada a Servicios de Directorio:

      DirectoryEntry entry = new DirectoryEntry("LDAP://OurDomain");
      DirectorySearcher Dsearch = new DirectorySearcher(entry);
      Dsearch.Filter = "(SAMAccountName=" + UserID + ")";
      Dsearch.PropertiesToLoad.Add("cn");

Si bien esto ha funcionado bien hasta ahora, debo informarles que todavía lo estoy probando y que el código anterior no ha tenido ningún motivo para ejecutarse, por lo que está sujeto a eliminación...Actualmente, las pruebas incluyen intentar descubrir un caso en el que el segundo conjunto de códigos sea más útil.Nuevamente, este es un trabajo en progreso, pero como podría ser de alguna ayuda o estimular tu cerebro para obtener algunas ideas, decidí agregarlo ahora...Lo actualizaré con los resultados finales una vez que se hayan realizado todas las pruebas.

Para aquellos que no saben C# aquí está ActionAttribute que regresa 400 en lugar de 401, y 'traga' el cuadro de diálogo de autenticación básica.

public class NoBasicAuthDialogAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        base.HandleUnauthorizedRequest(filterContext);
        filterContext.Result = new HttpStatusCodeResult(400);
    }
}

utilizar como sigue:

[NoBasicAuthDialogAuthorize(Roles = "A-Team")]
public ActionResult CarType()
{
 // your code goes here
}

Espero que esto te ahorre algo de tiempo.

Estoy usando Node, Express y Passport y tenía el mismo problema.Lo hice funcionar estableciendo explícitamente el www-authenticate encabezado a una cadena vacía.En mi caso, se veía así:

(err, req, res, next) => {
  if (err) {
    res._headers['www-authenticate'] = ''
    return res.json(err)
  }
}

¡Espero que ayude a alguien!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top