Pregunta

Aplasté mi cabeza contra esto un poco demasiado largo. ¿Cómo puedo evitar que un usuario navegue por las páginas de un sitio después de que se haya cerrado la sesión usando FormsAuthentication.SignOut? Espero que esto lo haga:

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

Pero no lo hace. Si escribo una URL directamente, todavía puedo navegar a la página. No he usado la seguridad de Roll-Your-Own en un tiempo, así que olvido por qué esto no funciona.

¿Fue útil?

Solución

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 se dice que las cookies se borrarán pero no lo hacen, error? Es exactamente igual con Session.Abandon () , la cookie sigue ahí.

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 . MSDN Reference .

Otros consejos

Me parece que no tiene configurada correctamente su sección de autorización web.config. Vea a continuación un ejemplo.

<authentication mode="Forms">
  <forms name="MyCookie" loginUrl="Login.aspx" protection="All" timeout="90" slidingExpiration="true"></forms>
</authentication>
<authorization>
  <deny users="?" />
</authorization>

Usando dos de las publicaciones anteriores de x64igor y Phil Haselden resolvió esto:

1. x64igor dio el ejemplo para hacer el cierre de 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 sobre cómo evitar el almacenamiento en caché después de cerrar la sesión:

  • Debe invalidar el 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 dices " Si escribo una URL directamente ... " ;.

Por defecto, 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 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 el 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();

También he luchado con esto antes.

Aquí hay una analogía de lo que parece estar pasando ... Un nuevo visitante, Joe, llega al sitio y se registra a través de la página de inicio de sesión utilizando FormsAuthentication. ASP.NET genera una nueva identidad para Joe y le da una cookie. Esa galleta 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 bloqueo 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 Joe regresa alguna vez, y si tiene esa clave perdida, ¡se lo deja volver!

Por lo que puedo decir, ¡no hay manera de decirle a ASP.NET que cambie la cerradura de la puerta!

La forma en que puedo vivir con esto es recordar el nombre de Joe en una variable de sesión. Cuando se desconecta, abandono la sesión, así que ya no tengo su nombre. Más tarde, para verificar si se le permite ingresar, simplemente comparo su nombre de identidad con el que tiene la sesión actual, y si no coinciden, no es un visitante válido.

En resumen, para un sitio web, NO confíe en User.Identity.IsAuthenticated sin verificar también sus variables de sesión.

Esto me funciona

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");
}

<li class="page-scroll">@Html.ActionLink("Log off", "LogOff", "Account")</li>

El código que publicaste 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.

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

¿Puedes publicar la configuración de 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 declaració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. Ya sea para modificar FormsAuthentication.RedirectToLoginPage (); estar

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

O para modificar el web.config agregando

<authorization>
  <deny users="?" />
</authorization>

En el segundo caso, durante el rastreo, el control no llegó a la página solicitada. Se ha redirigido inmediatamente a la URL de inicio de sesión antes de llegar al punto de interrupción. Por lo tanto, el método SignOut () no es el problema, el método de redirección es el único.

Espero que pueda ayudar a alguien

Saludos

Acabo de probar algunas de las sugerencias aquí y mientras pude usar el botón de retroceso del navegador, cuando hice clic en una selección de menú, el token [Autorizar] para ese [ActionResult] me envió de vuelta a la pantalla de inicio de sesión. / p>

Aquí está mi código de cierre de sesió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 hizo retroceder y mostró 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 usar.

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

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

se desconectará efectivamente del usuario. Sin embargo , si en la misma Solicitud necesita verificar Request.isAuthenticated (como puede suceder a menudo en un Filtro de Autorización, por ejemplo), encontrará que

Request.isAuthenticated == true

incluso _después de que hiciste 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 pasarme cuando configuré la autenticación > formas > Propiedad de ruta en Web.config . Al eliminar eso se solucionó el problema, y ??un simple FormsAuthentication.SignOut (); nuevamente eliminó la cookie.

Es posible que esté iniciando sesión desde un subdominio (sub1.dominio.com) y luego intente cerrar sesión desde un subdominio diferente (www.dominio.com).

Acabo de tener el mismo problema, donde SignOut () aparentemente no pudo eliminar correctamente el ticket. Pero solo en un caso específico, donde alguna otra lógica causó una redirección. Después de que eliminé 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 que no se activó la autenticación.

Ahora tengo un problema similar y creo que el problema en mi caso, así como en el póster original, se debe a la redirección. De forma predeterminada, un Response.Redirect genera una excepción que aumenta inmediatamente hasta que se detecta y se ejecuta la redirección de inmediato. Supongo que esto impide que la colección de cookies modificada se transmita al cliente. Si modifica su código para utilizar:

Response.Redirect("url", false);

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

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

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 " FormsAuthentication.SignOut () " declaración, 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é sirviendo esas páginas desde el caché. Es muy difícil conseguir que IE vacíe su caché, por lo que en muchas ocasiones, incluso después de cerrar sesión, escribe la URL de uno de los " asegurados " las páginas mostrarían el contenido en caché de antes.

(He visto este comportamiento incluso cuando te registras como un usuario diferente, e IE muestra la barra de " Bienvenida " en la parte superior de tu página, con el nombre de usuario del usuario anterior. Hoy en día, normalmente una recarga lo actualizará , pero si es persistente, aún 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 se produce si vas a una página protegida, te desconectas y entras en el historial de tu navegador. No es un gran problema, pero sigue siendo un poco molesto.

Sin embargo, tratar de ir a través de enlaces en mi aplicación web funciona correctamente.

Configurarlo para que no realice 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 alguna información para ayudar a entender el problema. La autenticación de formularios permite almacenar los datos del 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.

Según a Microsoft :

  

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

Al mismo tiempo, dicen :

  

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

Por último, con respecto a UseDeviceProfile, dicen :

  

Si la propiedad CookieMode está establecida en UseDeviceProfile, el   La propiedad CookiesSupported devolverá verdadero si el navegador para    la Solicitud actual admite tanto las cookies como la redirección de cookies ;   de lo contrario, la propiedad CookiesSupported devolverá false.

Al juntar todo esto, dependiendo del navegador del usuario, la configuración predeterminada puede dar como resultado que CookiesSupported sea true , 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. Espero que SignOut logre que el usuario finalice la sesión en cualquier circunstancia.

Una forma de hacer que SignOut funcione por sí misma es cambiando el modo de cookie a " UseCookies " (es decir, se requieren cookies) en el archivo web.config:

<authentication mode="Forms">
  <forms loginUrl="~/Account/SignIn" cookieless="UseCookies"/>
</authentication>

De acuerdo con mis pruebas, al hacer esto, SignOut funciona solo a costa de su sitio y ahora requiere 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 SENSIBLE AL CASO . WIF responde con la marca verde de verificación OK, pero no enviará el comando para eliminar las cookies al navegador.

Por lo tanto, debe prestar atención a la sensibilidad a las 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 pone en minúscula. 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 acuerdo con el navegador. Por lo tanto, para este Identity Server 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.

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

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