Mira la lección en vídeo
Accede al vídeo completo de esta lección y a más contenido exclusivo con el Plan Plus.
Desbloquear Plan PlusControl de acceso por roles
El control de acceso por roles permite restringir el acceso a diferentes partes de una aplicación según el tipo de usuario. En Flask, podemos implementar este sistema utilizando decoradores personalizados que verifican los permisos del usuario autenticado antes de ejecutar una vista.
Para implementar un sistema básico de roles, necesitamos primero definir los roles disponibles en nuestra aplicación. Podemos hacerlo mediante una enumeración o constantes:
from enum import Enum
class Role(Enum):
ADMIN = "admin"
MODERATOR = "moderator"
USER = "user"
Nuestro modelo de usuario debe incluir un campo para almacenar el rol asignado:
from flask_sqlalchemy import SQLAlchemy
from flask_login import UserMixin
db = SQLAlchemy()
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
password_hash = db.Column(db.String(128))
role = db.Column(db.String(20), default=Role.USER.value)
def has_role(self, role):
"""Verifica si el usuario tiene un rol específico"""
return self.role == role.value
def is_admin(self):
"""Método de conveniencia para verificar si es administrador"""
return self.role == Role.ADMIN.value
Creación del decorador de autorización
El decorador de autorización es el componente central que verifica si un usuario tiene los permisos necesarios:
from functools import wraps
from flask import abort
from flask_login import current_user
def require_role(required_role):
"""
Decorador que requiere un rol específico para acceder a una vista
"""
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
# Verificar si el usuario está autenticado
if not current_user.is_authenticated:
abort(401) # No autorizado
# Verificar si tiene el rol requerido
if not current_user.has_role(required_role):
abort(403) # Prohibido
return f(*args, **kwargs)
return decorated_function
return decorator
También podemos crear un decorador más flexible que acepte múltiples roles:
def require_roles(*allowed_roles):
"""
Decorador que permite acceso a usuarios con cualquiera de los roles especificados
"""
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if not current_user.is_authenticated:
abort(401)
# Verificar si el usuario tiene alguno de los roles permitidos
user_has_permission = any(
current_user.has_role(role) for role in allowed_roles
)
if not user_has_permission:
abort(403)
return f(*args, **kwargs)
return decorated_function
return decorator
Aplicación práctica en rutas
Una vez definidos los decoradores, podemos aplicarlos a nuestras rutas protegidas:
from flask import Flask, render_template
from flask_login import login_required
app = Flask(__name__)
@app.route('/admin/dashboard')
@login_required
@require_role(Role.ADMIN)
def admin_dashboard():
"""Panel de administración - solo para administradores"""
return render_template('admin/dashboard.html')
@app.route('/moderate/posts')
@login_required
@require_roles(Role.ADMIN, Role.MODERATOR)
def moderate_posts():
"""Moderación de posts - para admins y moderadores"""
posts = Post.query.filter_by(status='pending').all()
return render_template('moderate/posts.html', posts=posts)
@app.route('/user/profile')
@login_required
def user_profile():
"""Perfil de usuario - para cualquier usuario autenticado"""
return render_template('user/profile.html')
Sistema de jerarquía de roles
Guarda tu progreso
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
Para aplicaciones más complejas, podemos implementar un sistema jerárquico donde ciertos roles incluyen los permisos de roles inferiores:
class RoleHierarchy:
"""Define la jerarquía de roles y sus permisos"""
HIERARCHY = {
Role.ADMIN: [Role.ADMIN, Role.MODERATOR, Role.USER],
Role.MODERATOR: [Role.MODERATOR, Role.USER],
Role.USER: [Role.USER]
}
@classmethod
def has_permission(cls, user_role, required_role):
"""Verifica si un rol tiene permisos para realizar una acción"""
user_role_enum = Role(user_role)
allowed_roles = cls.HIERARCHY.get(user_role_enum, [])
return required_role in allowed_roles
def require_role_hierarchical(required_role):
"""
Decorador que considera la jerarquía de roles
"""
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if not current_user.is_authenticated:
abort(401)
if not RoleHierarchy.has_permission(current_user.role, required_role):
abort(403)
return f(*args, **kwargs)
return decorated_function
return decorator
Manejo de errores de autorización
Es importante proporcionar páginas de error personalizadas para mejorar la experiencia del usuario:
@app.errorhandler(403)
def forbidden(error):
"""Página de error para acceso prohibido"""
return render_template('errors/403.html'), 403
@app.errorhandler(401)
def unauthorized(error):
"""Página de error para usuarios no autenticados"""
return render_template('errors/401.html'), 401
En las plantillas Jinja, podemos mostrar contenido condicional según el rol:
<!-- En la plantilla base.html -->
{% if current_user.is_authenticated %}
{% if current_user.is_admin() %}
<a href="{{ url_for('admin_dashboard') }}">Panel Admin</a>
{% endif %}
{% if current_user.role in ['admin', 'moderator'] %}
<a href="{{ url_for('moderate_posts') }}">Moderar Posts</a>
{% endif %}
{% endif %}
Este enfoque proporciona un control de acceso granular y escalable, permitiendo que la aplicación crezca manteniendo la seguridad y organización del código.
Aprendizajes de esta lección de Flask
- Comprender el concepto de control de acceso por roles en aplicaciones web.
- Definir roles y asignarlos a usuarios en un modelo de datos.
- Crear decoradores personalizados para verificar permisos antes de acceder a rutas.
- Implementar un sistema jerárquico de roles para permisos escalables.
- Manejar errores de autorización y mostrar contenido condicional en plantillas según el rol.
Completa este curso de Flask y certifícate
Únete a nuestra plataforma de cursos de programación 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