Configuración Flask-Login
Flask-Login es una extensión que simplifica la gestión de sesiones de usuario en aplicaciones web Flask. Esta biblioteca maneja automáticamente las tareas comunes de autenticación como recordar qué usuarios han iniciado sesión, proteger vistas que requieren autenticación y gestionar el ciclo de vida de las sesiones.
La configuración inicial requiere instalar la extensión y establecer algunos componentes fundamentales que trabajarán en conjunto con nuestros modelos de usuario existentes.
Instalación y configuración básica
Para comenzar, instalamos Flask-Login mediante pip:
pip install Flask-Login
Una vez instalada, necesitamos configurar la extensión en nuestra aplicación Flask. La configuración básica requiere inicializar el LoginManager y establecer una clave secreta para las sesiones:
from flask import Flask
from flask_login import LoginManager
app = Flask(__name__)
app.config['SECRET_KEY'] = 'tu-clave-secreta-muy-segura'
# Inicializar LoginManager
login_manager = LoginManager()
login_manager.init_app(app)
# Configurar la vista de login
login_manager.login_view = 'login'
login_manager.login_message = 'Debes iniciar sesión para acceder a esta página.'
El LoginManager actúa como el coordinador central de todas las operaciones de autenticación. La propiedad login_view
especifica qué ruta debe mostrar el formulario de inicio de sesión cuando un usuario no autenticado intenta acceder a una página protegida.
Adaptación del modelo de usuario
Flask-Login requiere que nuestro modelo de usuario implemente ciertos métodos específicos. La forma más sencilla es heredar de UserMixin, que proporciona implementaciones predeterminadas:
from flask_sqlalchemy import SQLAlchemy
from flask_login import UserMixin
db = SQLAlchemy(app)
class Usuario(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(120), unique=True, nullable=False)
password_hash = db.Column(db.String(255), nullable=False)
activo = db.Column(db.Boolean, default=True)
def __repr__(self):
return f'<Usuario {self.email}>'
UserMixin proporciona automáticamente los métodos requeridos por Flask-Login:
is_authenticated
: DevuelveTrue
si el usuario ha proporcionado credenciales válidasis_active
: DevuelveTrue
si la cuenta del usuario está activais_anonymous
: DevuelveFalse
para usuarios reales,True
para usuarios anónimosget_id()
: Devuelve un identificador único para el usuario como string
Función de carga de usuario
Flask-Login necesita saber cómo cargar un usuario desde la base de datos usando su identificador. Esto se configura mediante el decorador user_loader
:
@login_manager.user_loader
def load_user(user_id):
return Usuario.query.get(int(user_id))
Esta función se ejecuta automáticamente cuando Flask-Login necesita recuperar información del usuario actual desde la sesión. El parámetro user_id
corresponde al valor devuelto por el método get_id()
del usuario.
Configuración de mensajes personalizados
Flask-Login permite personalizar los mensajes de error y redirección que se muestran a los usuarios:
# Configurar mensajes personalizados
login_manager.login_message = 'Por favor, inicia sesión para continuar.'
login_manager.login_message_category = 'info'
# Configurar página para usuarios no autorizados
login_manager.needs_refresh_message = 'Tu sesión ha expirado, por favor inicia sesión nuevamente.'
login_manager.needs_refresh_message_category = 'warning'
La propiedad login_message_category
define el tipo de mensaje que se mostrará en las plantillas, útil para aplicar diferentes estilos CSS según el contexto.
Configuración avanzada de sesiones
Para aplicaciones que requieren mayor control sobre las sesiones, podemos configurar opciones adicionales:
from datetime import timedelta
# Configurar duración de sesión
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=2)
# Configurar cookies de sesión
app.config['SESSION_COOKIE_SECURE'] = True # Solo HTTPS en producción
app.config['SESSION_COOKIE_HTTPONLY'] = True # Prevenir acceso desde JavaScript
app.config['SESSION_COOKIE_SAMESITE'] = 'Lax' # Protección CSRF básica
Estas configuraciones mejoran la seguridad de las sesiones estableciendo límites de tiempo y restricciones en las cookies que almacenan la información de sesión.
Integración con la aplicación principal
Una vez configurados todos los componentes, la estructura básica de nuestra aplicación quedaría así:
from flask import Flask, render_template, request, redirect, url_for, flash
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required
from werkzeug.security import check_password_hash
app = Flask(__name__)
app.config['SECRET_KEY'] = 'tu-clave-secreta-muy-segura'
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://usuario:password@localhost/mi_base_datos'
db = SQLAlchemy(app)
# Configuración Flask-Login
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'
login_manager.login_message = 'Debes iniciar sesión para acceder a esta página.'
@login_manager.user_loader
def load_user(user_id):
return Usuario.query.get(int(user_id))
# Modelo de usuario
class Usuario(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(120), unique=True, nullable=False)
password_hash = db.Column(db.String(255), nullable=False)
activo = db.Column(db.Boolean, default=True)
Esta configuración establece los fundamentos necesarios para que Flask-Login gestione automáticamente las sesiones de usuario, proporcionando una base sólida sobre la cual construir las funcionalidades de autenticación específicas de nuestra aplicación.
¿Te está gustando esta lección?
Inicia sesión para no perder tu progreso y accede a miles de tutoriales, ejercicios prácticos y nuestro asistente de IA.
Más de 25.000 desarrolladores ya confían en CertiDevs
Sesiones de usuario
Una vez configurado Flask-Login, podemos implementar las operaciones fundamentales de gestión de sesiones: iniciar sesión, cerrar sesión y proteger rutas que requieren autenticación. Estas operaciones trabajan en conjunto para crear un sistema de autenticación completo y seguro.
Implementación del inicio de sesión
El proceso de inicio de sesión combina la validación de credenciales con la creación de una sesión activa. Flask-Login proporciona la función login_user()
que establece automáticamente la sesión del usuario:
from flask import render_template, request, redirect, url_for, flash
from flask_login import login_user, current_user
from werkzeug.security import check_password_hash
@app.route('/login', methods=['GET', 'POST'])
def login():
# Redirigir si ya está autenticado
if current_user.is_authenticated:
return redirect(url_for('dashboard'))
if request.method == 'POST':
email = request.form['email']
password = request.form['password']
remember = request.form.get('remember', False)
# Buscar usuario en la base de datos
usuario = Usuario.query.filter_by(email=email).first()
# Verificar credenciales
if usuario and check_password_hash(usuario.password_hash, password):
login_user(usuario, remember=remember)
flash('Inicio de sesión exitoso', 'success')
# Redirigir a la página solicitada originalmente
next_page = request.args.get('next')
return redirect(next_page) if next_page else redirect(url_for('dashboard'))
else:
flash('Email o contraseña incorrectos', 'error')
return render_template('login.html')
La función login_user()
acepta un parámetro remember que determina si la sesión debe persistir después de cerrar el navegador. Cuando remember=True
, Flask-Login crea una cookie permanente que mantiene la sesión activa durante el tiempo configurado en PERMANENT_SESSION_LIFETIME
.
Acceso al usuario actual
Flask-Login proporciona el objeto current_user que permite acceder a la información del usuario autenticado desde cualquier parte de la aplicación:
from flask_login import current_user
@app.route('/perfil')
def perfil():
if current_user.is_authenticated:
return render_template('perfil.html', usuario=current_user)
else:
return redirect(url_for('login'))
El objeto current_user
está disponible automáticamente en las plantillas Jinja, lo que permite mostrar información personalizada sin necesidad de pasarla explícitamente:
<!-- En la plantilla HTML -->
{% if current_user.is_authenticated %}
<p>Bienvenido, {{ current_user.email }}</p>
<a href="{{ url_for('logout') }}">Cerrar sesión</a>
{% else %}
<a href="{{ url_for('login') }}">Iniciar sesión</a>
{% endif %}
Protección de rutas con decoradores
El decorador @login_required protege automáticamente las rutas que requieren autenticación. Cuando un usuario no autenticado intenta acceder a una ruta protegida, Flask-Login lo redirige automáticamente a la página de inicio de sesión:
from flask_login import login_required
@app.route('/dashboard')
@login_required
def dashboard():
return render_template('dashboard.html', usuario=current_user)
@app.route('/configuracion')
@login_required
def configuracion():
return render_template('configuracion.html')
Si un usuario intenta acceder a /dashboard
sin estar autenticado, Flask-Login lo redirigirá a /login?next=/dashboard
, preservando la URL de destino para redirigir correctamente después del inicio de sesión exitoso.
Implementación del cierre de sesión
La función logout_user() elimina la información de sesión del usuario y limpia las cookies relacionadas:
from flask_login import logout_user
@app.route('/logout')
@login_required
def logout():
logout_user()
flash('Has cerrado sesión correctamente', 'info')
return redirect(url_for('login'))
El decorador @login_required
en la ruta de logout asegura que solo usuarios autenticados puedan cerrar sesión, evitando errores innecesarios.
Gestión de sesiones con recordar usuario
Cuando un usuario selecciona la opción "Recordarme", Flask-Login gestiona automáticamente las cookies persistentes. Podemos personalizar este comportamiento:
from datetime import timedelta
@app.route('/login', methods=['POST'])
def login_post():
# ... validación de credenciales ...
if usuario and check_password_hash(usuario.password_hash, password):
remember = request.form.get('remember', False)
# Configurar duración personalizada para "recordar"
if remember:
login_user(usuario, remember=True, duration=timedelta(days=30))
else:
login_user(usuario, remember=False)
return redirect(url_for('dashboard'))
Verificación del estado de sesión
Flask-Login proporciona varios métodos de verificación que podemos usar para controlar el acceso y personalizar la experiencia del usuario:
@app.route('/area_restringida')
def area_restringida():
if not current_user.is_authenticated:
flash('Debes iniciar sesión para acceder', 'warning')
return redirect(url_for('login'))
if not current_user.is_active:
flash('Tu cuenta está desactivada', 'error')
logout_user()
return redirect(url_for('login'))
return render_template('area_restringida.html')
Manejo de sesiones expiradas
Para aplicaciones que requieren renovación de sesión, podemos implementar verificaciones adicionales:
from datetime import datetime, timedelta
@app.before_request
def verificar_sesion():
if current_user.is_authenticated:
# Verificar si la sesión ha estado inactiva demasiado tiempo
if 'last_activity' in session:
if datetime.now() - session['last_activity'] > timedelta(hours=2):
logout_user()
flash('Tu sesión ha expirado por inactividad', 'warning')
return redirect(url_for('login'))
# Actualizar timestamp de última actividad
session['last_activity'] = datetime.now()
Ejemplo completo de flujo de sesión
Un ejemplo práctico que integra todos los conceptos de gestión de sesiones:
@app.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('dashboard'))
if request.method == 'POST':
email = request.form.get('email')
password = request.form.get('password')
remember = bool(request.form.get('remember'))
usuario = Usuario.query.filter_by(email=email).first()
if usuario and usuario.activo and check_password_hash(usuario.password_hash, password):
login_user(usuario, remember=remember)
# Registrar último acceso
usuario.ultimo_acceso = datetime.utcnow()
db.session.commit()
next_page = request.args.get('next')
if next_page and is_safe_url(next_page):
return redirect(next_page)
return redirect(url_for('dashboard'))
else:
flash('Credenciales inválidas o cuenta desactivada', 'error')
return render_template('login.html')
def is_safe_url(target):
"""Verificar que la URL de redirección es segura"""
from urllib.parse import urlparse, urljoin
ref_url = urlparse(request.host_url)
test_url = urlparse(urljoin(request.host_url, target))
return test_url.scheme in ('http', 'https') and ref_url.netloc == test_url.netloc
Esta implementación completa maneja la autenticación segura, la persistencia de sesiones, la redirección apropiada y la validación de URLs para prevenir ataques de redirección maliciosa.
Aprendizajes de esta lección
- Comprender la instalación y configuración básica de Flask-Login en una aplicación Flask.
- Adaptar el modelo de usuario para integrarlo con Flask-Login mediante UserMixin.
- Implementar funciones para iniciar sesión, cerrar sesión y proteger rutas con autenticación.
- Gestionar sesiones persistentes y personalizar mensajes de autenticación.
- Aplicar buenas prácticas de seguridad en la gestión de sesiones y validación de URLs de redirección.
Completa Flask y certifícate
Únete a nuestra plataforma y accede a miles de tutoriales, ejercicios prácticos, proyectos reales y nuestro asistente de IA personalizado para acelerar tu aprendizaje.
Asistente IA
Resuelve dudas al instante
Ejercicios
Practica con proyectos reales
Certificados
Valida tus conocimientos
Más de 25.000 desarrolladores ya se han certificado con CertiDevs