DEV Community

Cover image for Contador de tiempo de sesion en Flask + Javascript
Hermann Pollack (hpollack95)
Hermann Pollack (hpollack95)

Posted on

Contador de tiempo de sesion en Flask + Javascript

Cuando se trabaja en sistemas con acceso de usuarios, cada lenguaje y/o framework asociado, tiene sus formas de manipular las sesiones de estas. Ahora bien, también se puede visualizar el tiempo restante de sesión de forma interactiva y vistosa. Acá hice un pequeño ejercicio para entender dos cosas: el manejo de tiempo de sesión en Flask y el como visualizarlo "contando hacia atrás", con Javascript.

Manejo de sesiones.

En Flask, el módulo de sesiones viene incluido en el framework. Esto lo invocamos en encabezado en los archivos de rutas. Como por ejemplo:

from flask import Blueprint, request, session, redirect, url_for, flash, render_template
Enter fullscreen mode Exit fullscreen mode

En el método de autenticación, podemos usar la lógica siguiente.

if data:
    session.permanent = True
    session['usuario'] = data
    DBUtils.set_history(session['usuario'][0], 'login', 'Inicio de Sesion Correcto')
    usuarioModel.set_ultimo_acceso(session['usuario'][0], 'login')
    return redirect(url_for('auth.home'))
Enter fullscreen mode Exit fullscreen mode

Donde podemos ver lo siguiente: despues de extraer la data, la verificamos y si existe, se crean la sesion. En session.permanent, al darle valor True, se mantiene activa, mientras que en la tupla session['usuario'], llenamos los datos de sesion. Esto sería lo básico para manejar las sesiones de usuario en un sistema tanto en Flask, como en otros frameworks como Django.

Ahora bien ¿Y si solo queremos unos minutos de sesion por seguridad? Podemos hacer eso de la siguiente manera. Ya que sabemos que session.permanent = True, permite que la sesión continúe activa aun cerrando el navegador, crearemos un límite usando otro método del núcleo de flask, que se invoca en el archivo principal.

Definir límite de tiempo de sesión.

Python

Lo primero es importar del núcleo de flask, el método current_app, que nos permitira crear una instancia válida para cualquier archivo de rutas, donde usamos sesiones.

from flask import current_app
Enter fullscreen mode Exit fullscreen mode

Luego, llamamos el siguiente método propio de flask

app.permanent_session_lifetime = timedelta(minutes=10)
Enter fullscreen mode Exit fullscreen mode

Este método, es el que maneja el tiempo de sesión. Para el ejemplo dejaremos 10 minutos, como límite. Ahora para invocarlo en todos los controladores, como ya habíamos mencionado, haremos lo siguiente: crearemos un contexto y definiremos una función en el archivo principal, que usara current_app para aplicarlo a todo el sitio.

@app.context_processor
def traer_restante():
    try:
        restante = int(current_app.permanent_session_lifetime.total_seconds())
    except Exception:
        restante = 600  # Valor por defecto (10 minutos)
    return {"restante": restante}
Enter fullscreen mode Exit fullscreen mode

Javascript: crear reloj contador "hacia atrás".

Ya que tenemos definido el tiempo de sesión, traeremos el valor de la funcion de contexto y lo aplicaremos al front creando un contador de tiempo hacia atrás. Para ello definiremos una función en javascript que nos dará ese efecto.

function contadorTiempo() {
    if (restante >= 0) {
        var minutos = Math.floor(restante / 60)
        var segundos = restante % 60
        document.getElementById('contador').innerText = `Tiempo de sesión restante: ${minutos}m ${segundos}s`
        restante--
        setTimeout(contadorTiempo, 1000)
        if (restante === 60) {
            alerta(2, 'Tu sesión terminará en un minuto')
        }
    } else {
        jconfirm({
            title: 'Sesión expirada',
            content: 'Tu sesión ha expirado. Por favor, inicia sesión nuevamente.',
            type: 'blue',
            buttons: {
                cerrar: {
                    btnClass: 'btn-info ripple',
                    action: function() {
                        window.location.href = '/login'
                    }
                }
            }
        })
    }
}
Enter fullscreen mode Exit fullscreen mode

Esta función toma el valor dela variable "restante" que definiremos a posteriori en la vista/template. Como no uso moment.js (que es una libreria útil para estas cosas, pero para el ejemplo no es necesario), aplicaremos el método Math.floor() para dividir el tiempo en minutos y segundos y colocarlos en un elemento del DOM de id contador, restando el valor de uno en uno y seteamos que el tiempo transcurra segundo a segundo con setTimeout().

Por último, creamos dos alertas. La primera es cuando quede menos de un minuto, una advertencia y el último, el que indica que la sesión expiro.

Ahora, debemos mostrar el resultado y para ello recurriré a un elemento div con id "contador" (en este caso, en el navbar), y al pie del archivo html se colocará el llamado a la función.

<div id="contador" class="ms-2"></div>
<!-- Bajo el </body> y los scripts usados se coloca el llamado a la funcion  -->
<script>
    // Como estamos llamando a valor del backend, usamos el formato de Jinja para traerlo.
    var restante = {{ restante|default(600)|int }}
    contadorTiempo() 
</script>
Enter fullscreen mode Exit fullscreen mode

El resultado final, será un contador de minutos y segundos que se verá algo así en la barra de navegación.

Conclusión.

Si bien, como mencioné antes, existen librerías como moment.js que simplifican esto, el realizarlo de esta manera sirve para entender mejor el manejo de sesiones y tiempo de vida de estas. Algo simple pero "inquebrantable" (o casi).

Les dejo un video del proceso.

Top comments (0)