FormsAuthentication.SignOut () no registra al usuario

Me golpeé la cabeza contra esto un poco demasiado tiempo. ¿Cómo evito que un usuario explore las páginas de un sitio después de que se hayan desconectado usando FormsAuthentication.SignOut? Yo esperaría que esto lo haga:

FormsAuthentication.SignOut(); Session.Abandon(); FormsAuthentication.RedirectToLoginPage(); 

Pero no es así Si escribo una URL directamente, igual puedo navegar a la página. No he utilizado la seguridad de rodar por su cuenta desde hace un tiempo, así que me olvido de por qué no funciona.

Los usuarios aún pueden navegar por su sitio web porque las cookies no se borran cuando llama a FormsAuthentication.SignOut() y se autentican en cada nueva solicitud. En la documentación de MS, dice que la cookie se borrará, pero no es así, ¿no? Es exactamente lo mismo con Session.Abandon() , cookie todavía está allí.

Debes cambiar tu código a esto:

 FormsAuthentication.SignOut(); Session.Abandon(); // clear authentication cookie HttpCookie cookie1 = new HttpCookie(FormsAuthentication.FormsCookieName, ""); cookie1.Expires = DateTime.Now.AddYears(-1); Response.Cookies.Add(cookie1); // clear session cookie (not necessary for your current problem but i would recommend you do it anyway) SessionStateSection sessionStateSection = (SessionStateSection)WebConfigurationManager.GetSection("system.web/sessionState"); HttpCookie cookie2 = new HttpCookie(sessionStateSection.CookieName, ""); cookie2.Expires = DateTime.Now.AddYears(-1); Response.Cookies.Add(cookie2); FormsAuthentication.RedirectToLoginPage(); 

HttpCookie está en el espacio de nombres System.Web . Referencia de MSDN .

Me parece que no tienes tu sección de autorización web configurada correctamente dentro de. Vea abajo para un ejemplo.

       

El uso de dos de las publicaciones anteriores por x64igor y Phil Haselden resolvió esto:

1. x64igor dio el ejemplo para cerrar la sesión:

  • Primero debe borrar la cookie de autenticación y la cookie de sesión devolviendo las cookies vacías en la respuesta al cierre de sesión.

     public ActionResult LogOff() { FormsAuthentication.SignOut(); Session.Clear(); // This may not be needed -- but can't hurt Session.Abandon(); // Clear authentication cookie HttpCookie rFormsCookie = new HttpCookie( FormsAuthentication.FormsCookieName, "" ); rFormsCookie.Expires = DateTime.Now.AddYears( -1 ); Response.Cookies.Add( rFormsCookie ); // Clear session cookie HttpCookie rSessionCookie = new HttpCookie( "ASP.NET_SessionId", "" ); rSessionCookie.Expires = DateTime.Now.AddYears( -1 ); Response.Cookies.Add( rSessionCookie ); 

2. Phil Haselden dio el ejemplo anterior de cómo evitar el almacenamiento en caché después de cerrar la sesión:

  • Debe invalidar la memoria caché en el lado del cliente a través de la respuesta .

      // Invalidate the Cache on the Client Side Response.Cache.SetCacheability( HttpCacheability.NoCache ); Response.Cache.SetNoStore(); // Redirect to the Home Page (that should be intercepted and redirected to the Login Page first) return RedirectToAction( "Index", "Home" ); } 

La clave aquí es que diga “Si escribo una URL directamente …”.

De forma predeterminada, en la autenticación de formularios, el navegador almacena en caché las páginas para el usuario. Por lo tanto, al seleccionar una URL directamente desde el menú desplegable de la dirección de los navegadores o al escribirla, PUEDE obtener la página de la memoria caché del navegador y nunca volver al servidor para verificar la autenticación / autorización. La solución a esto es evitar el almacenamiento en caché del lado del cliente en el evento Page_Load de cada página, o en el OnLoad () de su página base:

 Response.Cache.SetCacheability(HttpCacheability.NoCache); 

También puede llamar:

 Response.Cache.SetNoStore(); 

He luchado con esto antes también.

Aquí hay una analogía de lo que parece estar sucediendo … Un nuevo visitante, Joe, llega al sitio y se registra a través de la página de inicio de sesión usando FormsAuthentication. ASP.NET genera una nueva identidad para Joe y le da una cookie. Esa cookie es como la llave de la casa, y mientras Joe regrese con esa llave, puede abrir la cerradura. Cada visitante recibe una nueva clave y un nuevo candado para usar.

Cuando se llama a FormsAuthentication.SignOut() , el sistema le dice a Joe que pierda la clave. Normalmente, esto funciona, ya que Joe ya no tiene la llave, no puede entrar.

Sin embargo, si alguna vez Joe regresa, y tiene esa llave perdida, ¡lo vuelven a dejar entrar!

Por lo que puedo decir, ¡no hay forma de decirle a ASP.NET que cambie el candado de la puerta!

La forma en que puedo vivir con esto es recordar el nombre de Joe en una variable de sesión. Cuando cierra la sesión, abandono la sesión y ya no tengo su nombre. Más tarde, para verificar si está permitido, simplemente comparo su Identity.Name con lo que tiene la sesión actual, y si no coinciden, él no es un visitante válido.

En resumen, para un sitio web, NO confíe en User.Identity.IsAuthenticated sin consultar también las variables de Session.

Esto funciona para mí

 public virtual ActionResult LogOff() { FormsAuthentication.SignOut(); foreach (var cookie in Request.Cookies.AllKeys) { Request.Cookies.Remove(cookie); } foreach (var cookie in Response.Cookies.AllKeys) { Response.Cookies.Remove(cookie); } return RedirectToAction(MVC.Home.Index()); } 

Después de mucha búsqueda, finalmente, esto funcionó para mí. Espero que ayude.

 public ActionResult LogOff() { AuthenticationManager.SignOut(); HttpContext.User = new GenericPrincipal(new GenericIdentity(string.Empty), null); return RedirectToAction("Index", "Home"); } 
  • @Html.ActionLink("Log off", "LogOff", "Account")
  • El código que ha publicado parece que debería eliminar correctamente el token de autenticación de formularios, por lo que es posible que las carpetas / páginas en cuestión no estén realmente protegidas.

    ¿Has confirmado que no se puede acceder a las páginas antes de que se haya producido un inicio de sesión?

    ¿Puedes publicar la configuración web.config y el código de inicio de sesión que estás usando?

    He estado escribiendo una clase base para todas mis páginas y llegué al mismo problema. Tenía un código como el siguiente y no funcionó. Al rastrear, el control pasa de la instrucción RedirectToLoginPage () a la siguiente línea sin ser redirigido.

     if (_requiresAuthentication) { if (!User.Identity.IsAuthenticated) FormsAuthentication.RedirectToLoginPage(); // check authorization for restricted pages only if (_isRestrictedPage) AuthorizePageAndButtons(); } 

    Descubrí que hay dos soluciones. O para modificar FormsAuthentication.RedirectToLoginPage (); ser

     if (!User.Identity.IsAuthenticated) Response.Redirect(FormsAuthentication.LoginUrl); 

    O para modificar el web.config agregando

        

    En el segundo caso, mientras se realizaba el seguimiento, el control no llegaba a la página solicitada. Se redirigió de inmediato a la url de inicio de sesión antes de llegar al punto de ruptura. Por lo tanto, el método SignOut () no es el problema, el método de redireccionamiento es el indicado.

    Espero que eso pueda ayudar a alguien

    Saludos

    Acabo de probar algunas de las sugerencias aquí y, aunque pude utilizar el botón de retroceso del navegador, cuando hice clic en una selección de menú, el token [Authorize] para ese [ActionResult] me envió directamente a la pantalla de inicio de sesión.

    Aquí está mi código de desconexión:

      FormsAuthentication.SignOut(); Response.Cookies.Remove(FormsAuthentication.FormsCookieName); Response.Cache.SetExpires(DateTime.Now.AddSeconds(-1)); HttpCookie cookie = HttpContext.Request.Cookies[FormsAuthentication.FormsCookieName]; if (cookie != null) { cookie.Expires = DateTime.Now.AddDays(-1); Response.Cookies.Add(cookie); } 

    Aunque la función de retroceso en el navegador me llevó de vuelta y se muestra el menú seguro (todavía estoy trabajando en eso), no pude hacer nada que estuviera asegurado en la aplicación.

    Espero que esto ayude

    He intentado la mayoría de las respuestas en este hilo, sin suerte. Terminó con esto:

     protected void btnLogout_Click(object sender, EventArgs e) { FormsAuthentication.Initialize(); var fat = new FormsAuthenticationTicket(1, "", DateTime.Now, DateTime.Now.AddMinutes(-30), false, string.Empty, FormsAuthentication.FormsCookiePath); Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(fat))); FormsAuthentication.RedirectToLoginPage(); } 

    Lo encontré aquí: http://forums.asp.net/t/1306526.aspx/1

    Esta respuesta es técnicamente idéntica a Khosro.Pakmanesh. Lo estoy publicando para aclarar cómo su respuesta difiere de otras respuestas en este hilo, y en qué caso de uso se puede utilizar.

    En general, para borrar una sesión de usuario, haciendo

     HttpContext.Session.Abandon(); FormsAuthentication.SignOut(); 

    efectivamente cerrará la sesión del usuario. Sin embargo , si en la misma Solicitud necesita verificar Request.isAuthenticated (como suele suceder en un Filtro de autorización, por ejemplo), entonces encontrará que

     Request.isAuthenticated == true 

    incluso _después de haber hecho HttpContext.Session.Abandon() y FormsAuthentication.SignOut() .

    Lo único que funcionó fue hacer

     AuthenticationManager.SignOut(); HttpContext.User = new GenericPrincipal(new GenericIdentity(string.Empty), null); 

    Eso establece efectivamente Request.isAuthenticated = false .

    Esto comenzó a sucederme cuando establecí la autenticación> formularios> propiedad de ruta en Web.config . Al eliminar eso, se solucionó el problema y una simple FormsAuthentication.SignOut(); otra vez quitó la galleta.

    Podría ser que esté iniciando sesión desde un subdominio (sub1.domain.com) y luego intente cerrar la sesión desde un subdominio diferente (www.domain.com).

    Simplemente tuve el mismo problema, donde SignOut () aparentemente no eliminó correctamente el ticket. Pero solo en un caso específico, donde alguna otra lógica causó una redirección. Después de eliminar esta segunda redirección (la reemplacé con un mensaje de error), el problema desapareció.

    El problema debe haber sido que la página se redirigió en el momento equivocado, por lo tanto, no se activa la autenticación.

    Tengo un problema similar ahora y creo que el problema en mi caso, así como en el original, se debe a la redirección. De forma predeterminada, un Response.Redirect causa una excepción que se dispara inmediatamente hasta que se detecta y el redireccionamiento se ejecuta inmediatamente, supongo que esto impide que la colección de cookies modificada se transmita al cliente. Si modifica su código para usar:

     Response.Redirect("url", false); 

    Esto evita la excepción y parece permitir que la cookie se envíe correctamente al cliente.

    Intente enviar una variable de sesión cuando presione iniciar sesión. Y en la página de bienvenida, primero compruebe si esa sesión está vacía como esta en la carga de página o en el evento de inicio:

     if(Session["UserID"] == null || Session["UserID"] == "") { Response.Redirect("Login.aspx"); } 

    Para mí, el siguiente enfoque funciona. Creo que si hay algún error después de la statement “FormsAuthentication.SignOut ()”, SingOut no funciona.

     public ActionResult SignOut() { if (Request.IsAuthenticated) { FormsAuthentication.SignOut(); return Redirect("~/"); } return View(); } 

    ¿Estás probando / viendo este comportamiento usando IE? Es posible que IE esté publicando esas páginas desde el caché. Es notoriamente difícil conseguir que IE limpie su caché, y en muchas ocasiones, incluso después de cerrar la sesión, al escribir la URL de una de las páginas “aseguradas” se mostraría el contenido almacenado en caché desde antes.

    (He visto este comportamiento incluso cuando inicias sesión como un usuario diferente, y IE muestra la barra de “Bienvenida” en la parte superior de la página, con el nombre de usuario del usuario anterior. Actualmente, normalmente una recarga lo actualizará, pero si es persistente , todavía podría ser un problema de almacenamiento en caché.)

    Hacer Session.abandon () y destruir la cookie funciona bastante bien. Estoy usando mvc3 y parece que el problema ocurre si vas a una página protegida, cierras sesión y pasas a través del historial de tu navegador. No es un gran problema, pero todavía un poco molesto.

    Sin embargo, intentar pasar por enlaces en mi aplicación web funciona de la manera correcta.

    Configurarlo para que no funcione en el almacenamiento en caché del navegador puede ser el camino a seguir.

    Para MVC esto funciona para mí:

      public ActionResult LogOff() { FormsAuthentication.SignOut(); return Redirect(FormsAuthentication.GetRedirectUrl(User.Identity.Name, true)); } 

    Quería agregar algo de información para ayudar a entender el problema. Autenticación de formularios permite almacenar datos de usuario en una cookie o en la cadena de consulta de la URL. El método que admite su sitio se puede configurar en el archivo web.config.

    De acuerdo con Microsoft :

    El método SignOut elimina la información del ticket de autenticación de formularios de la cookie o la URL si CookiesSupported es falso .

    Al mismo tiempo, dicen :

    Uno de los valores de HttpCookieMode que indica si la aplicación está configurada para autenticación de formularios sin cookies. El valor predeterminado es UseDeviceProfile .

    Por último, con respecto a UseDeviceProfile, dicen :

    Si la propiedad CookieMode está configurada en UseDeviceProfile, la propiedad CookiesSupported será verdadera si el navegador de la solicitud actual admite ambas cookies y redirige las cookies ; de lo contrario, la propiedad CookiesSupported devolverá false.

    Al unir todo esto, dependiendo del navegador del usuario, la configuración predeterminada puede dar como resultado que CookiesSupported sea verdadero , lo que significa que el método SignOut no borra el ticket de la cookie. Esto parece contrario a la intuición y no sé por qué funciona de esta manera. Esperaría que SignOut realmente firmara al usuario bajo cualquier circunstancia.

    Una forma de hacer que el inicio de sesión funcione por sí solo es cambiar el modo de cookies a “Usar cookies” (es decir, se requieren cookies) en el archivo web.config:

        

    De acuerdo con mis pruebas, hacer esto hace que SignOut trabaje solo a costa de que su sitio requiera que las cookies funcionen correctamente.

    Tenga en cuenta que WIF se niega a decirle al navegador que limpie las cookies si el mensaje wsignoutcleanup de STS no coincide con la url con el nombre de la aplicación de IIS, y me refiero a CASE SENSITIVE . WIF responde con la marca verde OK, pero no enviará el comando para eliminar las cookies al navegador.

    Por lo tanto, debe prestar atención a la sensibilidad de mayúsculas y minúsculas de su url.

    Por ejemplo, ThinkTecture Identity Server guarda las direcciones URL de los RP visitantes en una cookie, pero las hace minúsculas. WIF recibirá el mensaje wsignoutcleanup en minúsculas y lo comparará con el nombre de la aplicación en IIS. Si no coincide, no elimina las cookies, pero informará de ello al navegador. Entonces, para este Servidor de Identidades, necesitaba escribir todas las direcciones URL en web.config y todos los nombres de las aplicaciones en IIS en minúsculas, para evitar tales problemas.

    Además, no olvide permitir las cookies de terceros en el navegador si tiene las aplicaciones fuera del subdominio de STS, de lo contrario, el navegador no eliminará las cookies, incluso si WIF así lo indica.