Tenemos una ASP.NET 4.5 Formularios de solicitud de uso de las formas nativas de autenticación de la sesión y de la funcionalidad. Ambos tienen un tiempo de espera de 20 minutos con el plazo de caducidad.

Imagine el siguiente escenario. Un usuario ha trabajado en nuestra aplicación por un tiempo y luego procede a hacer algunas otras cosas, de salir de nuestra aplicación inactivo durante 20 minutos. Luego, el usuario regresa a nuestra aplicación para escribir un informe. Sin embargo, cuando el usuario intenta guardar, él/ella es tratada con la pantalla de inicio de sesión, y el informe se pierde.

Obviamente, esto no deseadas. En lugar de este escenario, se desea que el navegador se redirige a la página de inicio de sesión en el momento en cualquiera de autenticación o sesión ha caducado. Para darse cuenta de esto, hemos de construir una Web de servicio de Api que se puede llamar para comprobar si este es el caso.

public class SessionIsActiveController : ApiController
{
    ///<summary>
    ///Gets a value defining whether the session that belongs with the current HTTP request is still active or not.
    ///</summary>
    ///<returns>True if the session, that belongs with the current HTTP request, is still active; false, otherwise./returns>
    public bool GetSessionIsActive()
    {
        CookieHeaderValue cookies = Request.Headers.GetCookies().FirstOrDefault();
        if (cookies != null && cookies["authTicket"] != null && !string.IsNullOrEmpty(cookies["authTicket"].Value) && cookies["sessionId"] != null && !string.IsNullOrEmpty(cookies["sessionId"].Value))
        {
            var authenticationTicket = FormsAuthentication.Decrypt(cookies["authTicket"].Value);
            if (authenticationTicket.Expired) return false;
            using (var asdc = new ASPStateDataContext()) //LINQ2SQL connection to the database where our session objects are stored
            {
                var expirationDate = SessionManager.FetchSessionExpirationDate(cookies["sessionId"].Value + ApplicationIdInHex, asdc);
                if (expirationDate == null || DateTime.Now.ToUniversalTime() > expirationDate.Value) return false;
            }
            return true;
        }
        return false;
    }
}

Esta Web de servicio de Api se llama cada 10 segundos por el cliente para comprobar si la autenticación o sesión ha caducado. Si es así, la secuencia de comandos redirige el navegador a la página de inicio de sesión. Esto funciona como un encanto.

Sin embargo, la llamada a este servicio desencadena el plazo de caducidad de la autenticación y la sesión. Por lo tanto, esencialmente, la creación de nunca acabar y autenticación de sesión. He establecer un punto de interrupción en el inicio del servicio para verificar si se trata de uno de nuestras propias funciones que desencadena este. Pero este no es el caso, parece producirse en algún lugar más profundo en ASP.NET antes de la ejecución del servicio.

  1. Hay una forma de desactivar la activación de ASP.NET’s de autenticación de la sesión y de deslizamiento de vencimientos de una solicitud específica?
  2. Si no, ¿cuál es la mejor práctica para hacer frente a una situación como esta?
  • La mejor práctica sería dejar de usar el lado del servidor sesiones. Son fundamentalmente roto el concepto de la web.
  • Soy consciente de esto, y en realidad estamos considerando la posibilidad de eliminar el uso de sesiones, pero incluso en esta perfecto sessionless mundo, el problema sería aún existen para el vale de autenticación…
  • De verdad que no. Cuando los agentes de usuario que se permite hacer el auth apretón de manos correctamente, el usuario no pierde su estado actual. Es el navegador redirigir a un formulario de inicio de sesión que hace que el usuario pierda su trabajo.
  • Desafortunadamente este es el modo de autenticación de formularios en ASP.NET las obras, cuando un auth billete expira el agente de usuario es siempre redirigido a otro, predefinida página. Sus sugerencias, básicamente, sugieren que no usamos ASP.NET’s de autenticación de formularios y de la sesión (que, yo os doy, tiene algunos méritos a ella). Sin embargo, en el interés de no tener que refactorizar nuestro marco de trabajo a tal grado, todavía estoy interesado en la respuesta a mi primera pregunta.
  • Sí, me doy cuenta de que mi respuesta no fue directamente útil, que es por qué no me pongo como una respuesta 🙂 por Desgracia, no se puede ser más útil como yo no uso las formas de autenticación.
  • Creo que no se puede deshabilitar la sesión de vencimiento para solicitudes específicas. Lo que usted podría ser capaz de hacer es hacer algo en clientside que va a mantener esta sesión en vivo. Sin embargo, esta es la desventaja de usar Formulario de Autenticación. Idealmente, nos debe mover sin cookies de autenticación; puede ser mediante el uso de algunos Tokens de Autenticación.
  • no estamos tratando de evitar el vencimiento para solicitudes específicas. Queremos evitar que la renovación en el plazo de caducidad para solicitudes específicas (que aún no ha expirado).

3 Comentarios

  1. 13
    1. Esto parece ser imposible. Una vez que el plazo de caducidad está habilitado, siempre es activa. Si hay una manera de acceder a la sesión sin la ampliación, no hemos sido capaces de encontrarlo.

    2. Entonces, ¿cómo hacer frente a este escenario? Se nos ocurrió con las siguientes alternativas de solución para el que fue originalmente propuesto en la pregunta. Este es el más eficiente porque no utilizar un servicio web para teléfono de la casa cada x segundos.

    Así que queremos tener una manera de saber cuando ASP.NET’s la autenticación de formularios o de la sesión ha caducado, por lo que podemos pro-activamente cierre de sesión del usuario. Un simple javascript temporizador en cada página (como propuesta por Khalid Abuhakmeh) no sería suficiente, ya que el usuario puede trabajar con la aplicación en múltiples ventanas del navegador/pestañas al mismo tiempo.

    La primera decisión que hemos tomado para hacer este problema más simple es hacer que el tiempo de caducidad de la sesión de un par de minutos más largo que el tiempo de vencimiento de la autenticación de formularios. De esta manera, la sesión no caducará nunca antes de la autenticación de formularios. Si hay una prolongada sesión de edad, la próxima vez que el usuario intenta iniciar sesión, se abandona a la fuerza un nuevo uno.

    Bien, así que ahora sólo tenemos que echar la autenticación de formularios de caducidad en cuenta.

    Siguiente, hemos decidido deshabilitar la autenticación de formularios automática del plazo de caducidad (como se establece en la web.config) y crear nuestra propia versión de la misma.

    public static void RenewAuthenticationTicket(HttpContext currentContext)
    {
        var authenticationTicketCookie = currentContext.Request.Cookies["AuthTicketNameHere"];
        var oldAuthTicket = FormsAuthentication.Decrypt(authenticationTicketCookie.Value);
        var newAuthTicket = oldAuthTicket;
        newAuthTicket = FormsAuthentication.RenewTicketIfOld(oldAuthTicket); //This triggers the regular sliding expiration functionality.
        if (newAuthTicket != oldAuthTicket)
        {
            //Add the renewed authentication ticket cookie to the response.
            authenticationTicketCookie.Value = FormsAuthentication.Encrypt(newAuthTicket);
            authenticationTicketCookie.Domain = FormsAuthentication.CookieDomain;
            authenticationTicketCookie.Path = FormsAuthentication.FormsCookiePath;
            authenticationTicketCookie.HttpOnly = true;
            authenticationTicketCookie.Secure = FormsAuthentication.RequireSSL;
            currentContext.Response.Cookies.Add(authenticationTicketCookie);
            //Here we have the opportunity to do some extra stuff.
            SetAuthenticationExpirationTicket(currentContext);
        }
    }

    Podemos llamar a este método desde el OnPreRenderComplete evento en nuestra aplicación BasePage de clase, a partir de la cual todas las otras páginas hereda. Hace exactamente la misma cosa que el normal, el plazo de caducidad de la funcionalidad, pero tenemos la oportunidad de hacer algunas cosas extras, como el de llamar a nuestro SetAuthenticationExpirationTicket método.

    public static void SetAuthenticationExpirationTicket(HttpContext currentContext)
    {
        //Take the current time, in UTC, and add the forms authentication timeout (plus one second for some elbow room ;-)
        var expirationDateTimeInUtc = DateTime.UtcNow.AddMinutes(FormsAuthentication.Timeout.TotalMinutes).AddSeconds(1);
        var authenticationExpirationTicketCookie = new HttpCookie("AuthenticationExpirationTicket");
        //The value of the cookie will be the expiration date formatted as milliseconds since 01.01.1970.
        authenticationExpirationTicketCookie.Value = expirationDateTimeInUtc.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds.ToString("F0");
        authenticationExpirationTicketCookie.HttpOnly = false; //This is important, otherwise we cannot retrieve this cookie in javascript.
        authenticationExpirationTicketCookie.Secure = FormsAuthentication.RequireSSL;
        currentContext.Response.Cookies.Add(authenticationExpirationTicketCookie);
    }

    Ahora tenemos una cookie adicional a nuestra disposición que siempre representa la correcta autenticación de formularios tiempo de caducidad, incluso si el usuario trabaja en diferentes ventanas del navegador/pestañas. Después de todo, las cookies tienen un navegador de gran alcance. Ahora lo único que queda es una función de javascript para comprobar el valor de la cookie.

    function CheckAuthenticationExpiration() {
        var c = $.cookie("AuthenticationExpirationTicket");
        if (c != null && c != "" && !isNaN(c)) {
            var now = new Date();
            var ms = parseInt(c, 10);
            var expiration = new Date().setTime(ms);
            if (now > expiration) location.reload(true);
        }
    }

    (Tenga en cuenta que utilizamos jQuery Plugin Cookie para recuperar la cookie).

    Poner esta función en un intervalo, y los usuarios se registran en el momento de su o sus formas de autenticación ha caducado. Listo 🙂 otra ventaja de esta aplicación es que ahora tiene el control sobre la autenticación de formularios de vencimiento se extienda. Si quieres un montón de servicios web que no prorrogar la fecha de vencimiento, sólo que no llame a la RenewAuthenticationTicket método para ellos.

    Por favor, deja un comentario si tienes algo que añadir!

    • cuando la forma de la autenticación de tiempo establecido es de 15 minutos y SlidingExpiration es cierto, si en ese tipo de situación en la que cualquier usuario publique los datos después de cada pocos minutos a decir 2 minutos, a continuación, inicio de sesión de usuario no tienen fecha de caducidad ? dime. gracias
    • ¿tiene sentido esta línea var newAuthTicket = oldAuthTicket; de la rutina de llamada RenewAuthenticationTicket() supongo que podemos puede omitir newAuthTicket = oldAuthTicket buscando tu comentario.
    • 1. Sí, esta es la forma en el plazo de caducidad de las obras. 2. Si recuerdo correctamente, la línea no puede ser omitido, ya que la línea de abajo FormsAuthentication.RenewTicketIfOld(oldAuthTicket); solo da un resultado en caso de que el billete es ‘viejo’. Para la asignación del que hablas, asegura newAuthTicket siempre tiene un valor (referencias de algo, para ser más exactos). Usted puede experimentar con él mismo para ver.
    • hay dos líneas de 1ª var newAuthTicket = oldAuthTicket; and second one newAuthTicket = FormsAuthentication.RenewTicketIfOld(oldAuthTicket); así que sea cual sea el valor será almacenado en newAuthTicket la siguiente línea sobrescribirá que….si estoy en lo cierto, entonces ¿cuál es el significado de la primera línea var newAuthTicket = oldAuthTicket; no es muy claro para mí.
    • Me fui de nuevo y tenía una mejor mirada en ella, y estás en lo correcto. La línea es innecesario. Gracias por el aviso!
    • La razón de que las cookies de autenticación se establece HttpOnly es para prevenir un ataque de XSS de ser capaz de robar su valor de cookie y apropiarse de su sesión. Al exponer esto, se ha creado una vulnerabilidad de seguridad, creo. Si desea exponer el tiempo de vencimiento de JS, crear un tiempo de caducidad de la cookie y comprobar que en su lugar. Yo daría la bienvenida a un experto en seguridad para opinar sobre esto, pero al mismo tiempo ser consciente de que le está explícitamente la desactivación de una capa de protección en su seguridad.
    • muchas gracias por su preocupación. La sugerencia que dar como una posible solución, en realidad es lo que ya hay. La cookie que ha HttpOnly se establece en false (authenticationExpirationTicketCookie), es, de hecho, independiente del tiempo de expiración de la cookie. El real de la cookie de autenticación (authenticationTicketCookie) ha establecido explícitamente en verdad, como se puede ver en el primer bloque de código. Así que no debería haber ningún problema de seguridad, de acuerdo?
    • tienes razón y yo estaba equivocado. Voy a quitar la engañosa editar. Gracias por el suave corrección!
    • Estoy tratando de implementar esto en un vb.net aplicación, ya que es exactamente lo que estoy buscando. Pregunta necesito para crear la inicial de SetAuthenticationExpirationTicket cuando el billete se crea inicialmente en mi página de inicio de sesión? como viejo y newAuth entradas siempre parecen ser iguales.
    • Buen punto. Durante el inicio de sesión, siempre debe llamar a SetAuthenticationExpirationTicket, el proceso descrito anteriormente se describe el proceso a partir de entonces.

  2. 1

    Todo esto puede ser resuelto lado del cliente, sin la necesidad de ir de vuelta al servidor.

    En JavaScript ello.

     var timeout = setTimeout(function () {
          window.location = "/login";
     }, twentyMinutesInMilliseconds + 1);

    El tiempo de espera se establece en 20 minutos en cada actualización de la página. Esto garantiza que el usuario necesita para conseguir su trabajo hecho antes de que el tiempo pasa. Un montón de sitios que usan este método, y le ahorra haciendo innecesarias las solicitudes del servidor.

    • Esta sería una solución incompleta, no toma en cuenta que un usuario puede trabajar con la aplicación en múltiples ventanas del navegador/pestañas. Imaginar a un usuario trabajar con nuestra aplicación en fichas a y B. Cuando el usuario solicita/posts una página en la ficha B, el temporizador en Una ficha no sería restablecer y así salir de la sincronización.
    • Estoy de acuerdo con usted en que escenario es posible, pero no tenemos ni idea de cuál es el uso de los usuarios es como la de la pregunta anterior.
  3. 1

    Su sitio web debe funcionar sin JavaScript o simplemente reemplazar un problema con otro. He abordado este problema también y aquí es cómo fue resuelto:

    Cuando se autentica a sí mismo después de la cookie de sesión se crea con duración predeterminada en 20 min. Cuando este expire el usuario será desconectado.

    Sobre el plazo de caducidad de ASP.NET's de autenticación de formularios y de la sesión

    Cuando el usuario selecciona la opción «recordarme» en el signo en forma adicional y la persistencia de la cookie [AuthCookie] se creó en el lado del cliente y en la base de datos. Esta cookie tiene una duración de 1 mes. Cada vez que se carga la página, de sesión y de persistencia de la información de la cookie es recreado con un nuevo curso de la vida (normalmente desea descifrar/crypt el billete).

    Imagine el siguiente escenario. Un usuario ha trabajado en nuestra aplicación
    por un tiempo y luego procede a hacer algunas otras cosas, de salir de nuestra
    aplicación inactivo durante 20 minutos. A continuación, el usuario regresa a nuestro
    aplicación para escribir un informe. Cuando el usuario intenta guardar la sesión, la sesión se restaura antes de la solicitud.

    Una forma de hacer esto es para extender global.aspx para manejar prerequest. Algo en las líneas de:

        void application_PreRequestHandlerExecute(object sender, EventArgs e){
            ...
            if (HttpContext.Current.Handler is IRequiresSessionState) {
                if (!context.User.Identity.IsAuthenticated)
                    AuthService.DefaultProvider.AuthenticateUserFromExternalSource();

    AuthenticateUserFromExternalSource debe comprobar si los datos de cookies coincide con la base de datos, porque todo lo que esté almacenado en el lado del cliente puede ser cambiado. Si usted ha pagado los servicios con los derechos de acceso, entonces usted necesita para comprobar si el usuario todavía tiene esos derechos y, a continuación, puede volver a crear la sesión.

    • cuando la forma de la autenticación de tiempo establecido es de 15 minutos y SlidingExpiration es cierto, si en ese tipo de situación en la que cualquier usuario publique los datos después de cada pocos minutos a decir 2 minutos, a continuación, inicio de sesión de usuario no tienen fecha de caducidad ? dime. gracias

Dejar respuesta

Please enter your comment!
Please enter your name here