python

Login y sesiones en Flask

En este post de programación web con Python y Flask te enseñaré, de manera muy sencilla y fácil, cómo hacer un login y proteger una ruta para que solo accedan los usuarios que han iniciado sesión.

Básicamente vas a aprender cómo iniciar sesión en Flask y proteger todas tus rutas. Va a ser un ejemplo sencillo en donde nos vamos a enfocar solamente al manejo de sesiones y a la autenticación del usuario.

Formulario para login

Login e inicio de sesión con Flask y Python

Comencemos viendo el formulario. Es simple código HTML que vamos a procesar más tarde con este microframework que es Flask:

<!DOCTYPE html>
<html lang="es">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login</title>

    <link rel="stylesheet" href="https://unpkg.com/bulma@0.9.1/css/bulma.min.css">

</head>

<body>
    <section class="section">
        <div class="columns">
            <div class="column is-one-third is-offset-one-third">
                <h1 class="is-size-1">Bienvenido</h1>
                <form action="{{url_for('hacer_login')}}" method="post">
                    <label for="correo">Correo</label>
                    <div class="control">
                        <input autofocus required type="email" class="input" placeholder="Correo" id="correo"
                            name="correo">
                    </div>
                    <div class="control">
                        <label for="palabra_secreta">Contraseña</label>
                        <input required type="password" class="input" placeholder="Contraseña" id="palabra_secreta"
                            name="palabra_secreta">
                    </div>

                    <button class="button is-success mt-2">Entrar</button>
                    {# Mostrar mensajes / errores si es que existen #}
                    {% with mensajes_flash = get_flashed_messages() %}
                    {% if mensajes_flash %}
                    <div class="notification is-danger mt-2">
                        {% for mensaje in mensajes_flash %}
                        <li>{{ mensaje }}</li>
                        {% endfor %}
                        {% endif %}
                        {% endwith %}
                    </div>
                </form>
            </div>
        </div>
    </section>

</body>

</html>

Pon atención en la línea 19, el formulario será procesado en la ruta /hacer_login que vamos a ver a continuación.

Fíjate que estamos mostrando los mensajes flash en caso de que existan. Estos mensajes flash sirven para dar retroalimentación al usuario. Por ejemplo, si las credenciales que ingresó son erróneas, se le indica con un mensaje.

Ahora servimos esa plantilla con Flask:

# Formulario para iniciar sesión


@app.route("/login")
def login():
    return render_template("login.html")

De modo que cuando el usuario visite /login se le muestre el formulario.

Iniciando sesión

Ahora vamos a ver cómo procesar ese formulario e iniciar sesión con Flask en caso de que las credenciales sean correctas.

En este caso estoy haciendo la comprobación muy fácil por simplicidad. El código queda así:

@app.route("/hacer_login", methods=["POST"])
def hacer_login():
    correo = request.form["correo"]
    palabra_secreta = request.form["palabra_secreta"]
    # Aquí comparamos. Lo hago así de fácil por simplicidad
    # En la vida real debería ser con una base de datos y una contraseña hasheada
    if correo == "parzibyte@gmail.com" and palabra_secreta == "123":
        # Si coincide, iniciamos sesión y además redireccionamos
        session["usuario"] = correo
        # Aquí puedes colocar más datos. Por ejemplo
        # session["nivel"] = "administrador"
        return redirect("/escritorio")
    else:
        # Si NO coincide, lo regresamos
        flash("Correo o contraseña incorrectos")
        return redirect("/login")

Extraemos los valores del formulario en las líneas 3 y 4. Después comparamos esas credenciales, obviamente en la vida real estoy será con una base de datos (por ejemplo SQLite3) y con las contraseñas hasheadas (con Bcrypt, por ejemplo).

En caso de que las credenciales coincidan iniciamos la sesión en la línea 9, en donde modificamos la variable session. Y después redireccionamos al escritorio, que será una ruta protegida a la que solo se podrá acceder si se ha iniciado sesión.


# Protegida. Solo pueden entrar los que han iniciado sesión


@app.route("/escritorio")
def escritorio():
    return render_template("escritorio.html")

Para el caso de que la contraseña o el correo no coincidan, ponemos un mensaje flash (que será mostrado en el formulario de login) y redireccionamos de nuevo al mismo.

Protegiendo rutas

Ruta protegida – Solo usuarios logueados pueden entrar – Programación Flask y Python

Como te dije anteriormente, cuando se quiera acceder a cualquier ruta que esté protegida, solo los usuarios logueados podrán acceder. Para lograr esto debemos ejecutar cierto código antes de cada petición.

Flask nos permite hacer esto usando @app.before_request, en donde podemos interceptar las rutas y hacer cierta verificación dependiendo de la ruta a la que se acceda:

# Un "middleware" que se ejecuta antes de responder a cualquier ruta. Aquí verificamos si el usuario ha iniciado sesión
@app.before_request
def antes_de_cada_peticion():
    ruta = request.path
    # Si no ha iniciado sesión y no quiere ir a algo relacionado al login, lo redireccionamos al login
    if not 'usuario' in session and ruta != "/login" and ruta != "/hacer_login" and ruta != "/logout" and not ruta.startswith("/static"):
        flash("Inicia sesión para continuar")
        return redirect("/login")
    # Si ya ha iniciado, no hacemos nada, es decir lo dejamos pasar

Fíjate en que estamos verificando si el usuario no ha iniciado sesión con el if not 'usuario' in session, además de que estamos comprobando la ruta, ya que las rutas permitidas sin haber iniciado sesión son /login, /hacer_login, etcétera.

El punto es que si se intenta acceder a una ruta protegida sin iniciar sesión, se va a redirigir al usuario al login.

Nota: recuerda que siempre puedes imprimir la variable ruta (línea 4) para depurar en caso de que tengas problemas.

Poniendo todo junto

Ahora veamos el código completo. Lo dejaré en GitHub para que puedas examinar todas las vistas, plantillas, código, etcétera.

Recuerda que necesitas Python y PIP. Una vez que los tengas, simplemente instala las dependencias con:

pip install flask

Ahora abre una terminal en donde se encuentra el proyecto y ejecuta:

python main.py

Finalmente visita http://localhost:8000/login y deberías tener la vista del login.

Para terminar, te dejo con más posts de programación en Python y Flask.

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.
parzibyte

Programador freelancer listo para trabajar contigo. Aplicaciones web, móviles y de escritorio. PHP, Java, Go, Python, JavaScript, Kotlin y más :) https://parzibyte.me/blog/software-creado-por-parzibyte/

Entradas recientes

Desplegar PWA creada con Vue 3, Vite y SQLite3 en Apache

Ya te enseñé cómo convertir una aplicación web de Vue 3 en una PWA. Al…

3 días hace

Arquitectura para wasm con Go, Vue 3, Pinia y Vite

En este artículo voy a documentar la arquitectura que yo utilizo al trabajar con WebAssembly…

3 días hace

Vue 3 y Vite: crear PWA (Progressive Web App)

En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que…

3 días hace

Errores de Comlink y algunas soluciones

Al usar Comlink para trabajar con los workers usando JavaScript me han aparecido algunos errores…

3 días hace

Esperar promesa para inicializar Store de Pinia con Vue 3

En este artículo te voy a enseñar cómo usar un "top level await" esperando a…

3 días hace

Solución: Apache – Server unable to read htaccess file

Ayer estaba editando unos archivos que son servidos con el servidor Apache y al visitarlos…

4 días hace

Esta web usa cookies.