Python Flask – Implementación de autenticación de usuarios

Flask ofrece flexibilidad para implementar la autenticación de diversas maneras, pero uno de los métodos más comunes es utilizando la extensión Flask-Login junto con Flask-SQLAlchemy para manejar usuarios y sesiones. Aquí te muestro un ejemplo paso a paso de cómo implementar la autenticación de usuarios en Flask:

Paso 1: Instalar la extensión Flask Login

pip install flask_login

Paso 2: Crear el modelo

Puedes copiar y pegar este código completo, para efectos prácticos el modelo y controladores están dentro del mismo fichero:

app.py

from flask import Flask, render_template, request, redirect, url_for, flash
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user

app = Flask(__name__)
app.config['SECRET_KEY'] = 'tu_clave_secreta'
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://usuario:clave@localhost/basededatos'

db = SQLAlchemy(app)
migrate = Migrate(app, db)

login_manager = LoginManager(app)
login_manager.login_view = 'login'

class Usuario(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    nombre = db.Column(db.String(80), nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    password = db.Column(db.String(128))

@login_manager.user_loader
def load_user(user_id):
    return Usuario.query.get(int(user_id))

@app.route('/registro', methods=['GET', 'POST'])
def registro():
    if request.method == 'POST':
        nombre = request.form['nombre']
        email = request.form['email']
        password = request.form['password']
        nuevo_usuario = Usuario(nombre=nombre, email=email, password=password)
        db.session.add(nuevo_usuario)
        db.session.commit()
        flash('¡Registro exitoso! Ahora puedes iniciar sesión.')
        return redirect(url_for('login'))
    return render_template('registro.html')

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        email = request.form['email']
        password = request.form['password']
        usuario = Usuario.query.filter_by(email=email).first()
        if usuario and usuario.password == password:
            login_user(usuario)
            flash('Inicio de sesión exitoso.')
            return redirect(url_for('perfil'))
        else:
            flash('Credenciales incorrectas. Por favor, inténtalo de nuevo.')
    return render_template('login.html')

@app.route('/perfil')
@login_required
def perfil():
    return render_template('perfil.html')

@app.route('/logout')
@login_required
def logout():
    logout_user()
    flash('Has cerrado sesión.')
    return redirect(url_for('login'))

if __name__ == '__main__':
    with app.app_context():
        db.create_all()
    app.run(debug=True)

Paso 3: Crear los Templates:

Dentro de la carpeta templates, crear los siguientes archivos html. Si no se cuenta con esa carpeta, crearla manualmente:

templates/registro.html

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <title>Registro</title>
</head>
<body>
    <h1>Registro de Usuario</h1>
    
    {% with messages = get_flashed_messages() %}
    {% if messages %}
    <ul>
        {% for message in messages %}
        <li>{{ message }}</li>
        {% endfor %}
    </ul>
    {% endif %}
    {% endwith %}
    
    <form method="POST">
        <label for="nombre">Nombre:</label>
        <input type="text" name="nombre" required><br><br>
        
        <label for="email">Email:</label>
        <input type="email" name="email" required><br><br>
        
        <label for="password">Contraseña:</label>
        <input type="password" name="password" required><br><br>
        
        <button type="submit">Registrarse</button>
    </form>
    
    <p>¿Ya tienes una cuenta? <a href="{{ url_for('login') }}">Iniciar Sesión</a></p>
</body>
</html>

templates/login.html

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <title>Iniciar Sesión</title>
</head>
<body>
    <h1>Iniciar Sesión</h1>
    
    {% with messages = get_flashed_messages() %}
    {% if messages %}
    <ul>
        {% for message in messages %}
        <li>{{ message }}</li>
        {% endfor %}
    </ul>
    {% endif %}
    {% endwith %}
    
    <form method="POST">
        <label for="email">Email:</label>
        <input type="email" name="email" required><br><br>
        
        <label for="password">Contraseña:</label>
        <input type="password" name="password" required><br><br>
        
        <button type="submit">Iniciar Sesión</button>
    </form>
    
    <p>¿No tienes una cuenta? <a href="{{ url_for('registro') }}">Registrarse</a></p>
</body>
</html>

template/perfil.html

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <title>Perfil de Usuario</title>
</head>
<body>
    <h1>Perfil de Usuario</h1>
    
    {% with messages = get_flashed_messages() %}
    {% if messages %}
    <ul>
        {% for message in messages %}
        <li>{{ message }}</li>
        {% endfor %}
    </ul>
    {% endif %}
    {% endwith %}
    
    <p>Bienvenido, {{ current_user.nombre }}.</p>
    
    <p><a href="{{ url_for('logout') }}">Cerrar Sesión</a></p>
</body>
</html>

Paso 4: Preparar base de datos

Usaremos un modelo de datos Usuarios. Si ya tenemos la base de datos creada desde el capítulo anterior de este tutorial, agregaremos un campo password al modelo, asegúrate de realizar el la migración y upgrade antes de ejecutar el nuevo modelo.

$ flask db init
$ flask db migrate
$ flask db upgrade

Es posible que en el proceso de migración les muestre este error: ERROR [flask_migrate] Error: Target database is not up to date. Para ello se corregirá con este comando:

$ flask db stamp head

Paso 5: Ejecutar la app y aplicación web

$ python app.py
http://localhost:5000/registro
http://localhost:5000/login
http://localhost:5000/perfil

Deja un comentario