Café y Código
RUTA DE APRENDIZAJE · PARTE 2 DE 3LECCIONES 07–10

7.2 Guía Práctica: Sesiones y Permisos 🔐

Protección de rutas, inicio y cierre de sesión seguro, control de acceso con @login_required, grupos, permisos y decoradores propios.

4 lecciones en video centradas en autenticación, autorización y seguridad en el servidor.

PARTE 2 · LECCIONES 07–10

Autenticación, sesiones y permisos

Protege las rutas, administra la sesión y aplica reglas de acceso según el usuario.

LECCIÓN 07

Autenticación: login, logout y sesiones

Objetivo: Comprender cómo Django identifica usuarios y mantiene una sesión autenticada.

¿Qué aprenderás y por qué es importante?

Autenticación significa verificar la identidad de quien intenta ingresar; autorización significa decidir qué puede hacer una vez identificado. Django incorpora un sistema de usuarios y sesiones. Tras un inicio de sesión correcto, el navegador recibe una cookie de sesión; el servidor utiliza esa referencia para asociar solicitudes posteriores con el usuario autenticado. La contraseña no se guarda directamente en la cookie.

Explicación técnica paso a paso

authenticate comprueba las credenciales y login registra al usuario en la sesión. logout termina la sesión autenticada. El formulario de acceso utiliza POST y CSRF; las contraseñas deben tratarse con el sistema de hashing de Django, nunca guardarse como texto plano. Es recomendable cerrar sesión mediante POST.

Ejemplo práctico · Python / Django
cuentas/views.py
PYTHON
1# cuentas/views.py
2from django.contrib.auth import authenticate, login, logout
3from django.shortcuts import render, redirect
4from django.views.decorators.http import require_POST
5
6def iniciar_sesion(request):
7 error = None
8 if request.method == 'POST':
9 usuario = request.POST.get('username', '')
10 clave = request.POST.get('password', '')
11 user = authenticate(request, username=usuario, password=clave)
12 if user is not None:
13 login(request, user)
14 return redirect('listado_productos')
15 error = 'Credenciales incorrectas.'
16 return render(request, 'cuentas/login.html', {'error': error})
17
18@require_POST
19def cerrar_sesion(request):
20 logout(request)
21 return redirect('iniciar_sesion')
Ejemplo complementario · Comandos / HTML
templates/cuentas/login.html
HTML
1<!-- cuentas/login.html -->
2<form method="post">
3 {% csrf_token %}
4 <input name="username" autocomplete="username" required>
5 <input name="password" type="password" autocomplete="current-password" required>
6 <button type="submit">Ingresar</button>
7</form>
8{% if error %}<p role="alert">{{ error }}</p>{% endif %}
9
10<!-- Botón de salida en una página autenticada -->
11<form method="post" action="{% url 'cerrar_sesion' %}">
12 {% csrf_token %}
13 <button type="submit">Cerrar sesión</button>
14</form>
Atención y buenas prácticas: Django necesita SessionMiddleware y AuthenticationMiddleware. En producción, usar HTTPS y revisar las opciones de seguridad de cookies.
Actividad de aplicación: Probar credenciales válidas e inválidas, ingresar a una página y verificar que al cerrar sesión se pierde el acceso.
LECCIÓN 08

Proteger vistas con login_required

Objetivo: Restringir páginas a usuarios que hayan iniciado sesión.

¿Qué aprenderás y por qué es importante?

Una página no queda protegida por ocultar su enlace en el menú. Un visitante podría escribir directamente su URL. El decorador login_required comprueba en el servidor si request.user está autenticado; si no lo está, redirige al acceso configurado. Esto permite proteger listados, formularios y operaciones de mantenimiento.

Explicación técnica paso a paso

El decorador se coloca sobre la función que atiende la ruta. Debe aplicarse a todas las vistas que requieren autenticación, no solamente al index. LOGIN_URL indica a dónde redirigir a usuarios anónimos. Tras iniciar sesión se puede recuperar el destino original, pero debe validarse antes de redirigir a una URL proporcionada por el usuario.

Ejemplo práctico · Python / Django
settings.py y tienda/views.py
PYTHON
1# settings.py
2LOGIN_URL = 'iniciar_sesion'
3
4# tienda/views.py
5from django.contrib.auth.decorators import login_required
6
7@login_required
8def listado_productos(request):
9 productos = Producto.objects.all()
10 return render(request, 'tienda/listado.html', {'productos': productos})
11
12@login_required
13def crear_producto(request):
14 # Mantener aquí el flujo GET / POST de la lección 04
15 ...
Ejemplo complementario · Comandos / HTML
En una plantilla
HTML
1<!-- En una plantilla -->
2{% if user.is_authenticated %}
3 <p>Bienvenido, {{ user.username }}</p>
4{% else %}
5 <a href="{% url 'iniciar_sesion' %}">Iniciar sesión</a>
6{% endif %}
Atención y buenas prácticas: login_required solo comprueba autenticación, no si el usuario tiene permiso para modificar o borrar registros. Para eso se requieren controles adicionales.
Actividad de aplicación: Proteger las vistas de listado, creación, edición y eliminación. Probar la URL directa en una ventana privada.
LECCIÓN 09

Autorización por perfiles y permisos

Objetivo: Distinguir perfiles y restringir funcionalidades según responsabilidades.

¿Qué aprenderás y por qué es importante?

Un sistema puede tener usuarios autenticados con funciones diferentes. Por ejemplo, un administrador mantiene productos y un operador solo consulta el inventario. Django proporciona usuarios, grupos y permisos. Los grupos pueden representar perfiles organizacionales, mientras que los permisos permiten expresar acciones concretas. Esto es más seguro que confiar únicamente en el nombre de un perfil mostrado en la interfaz.

Explicación técnica paso a paso

La autenticación responde “¿quién eres?”; la autorización responde “¿puedes hacer esto?”. Para un ejemplo sencillo se puede asociar el usuario a un grupo y comprobarlo desde la vista. En proyectos más grandes conviene usar permisos de Django y asignarlos a grupos desde el panel de administración. La verificación debe hacerse en cada vista protegida.

Ejemplo práctico · Python / Django
tienda/views.py
PYTHON
1# Ejemplo con permisos nativos de Django
2from django.contrib.auth.decorators import login_required, permission_required
3
4@login_required
5@permission_required('tienda.add_producto', raise_exception=True)
6def crear_producto(request):
7 # Procesar formulario HTML y request.POST
8 ...
9
10# Ejemplo de consulta de grupo:
11def es_administrador(user):
12 return user.is_authenticated and user.groups.filter(
13 name='Administradores'
14 ).exists()
Ejemplo complementario · Comandos / HTML
templates/tienda/listado.html
HTML
1<!-- Ocultar opciones según permisos (solo presentación) -->
2{% if perms.tienda.add_producto %}
3 <a href="{% url 'crear_producto' %}">Nuevo producto</a>
4{% endif %}
Atención y buenas prácticas: Ocultar botones no reemplaza la autorización del servidor. Los permisos add, change, delete y view se crean normalmente para los modelos de Django.
Actividad de aplicación: Crear grupos Administradores y Operadores, asignar permisos diferentes y verificar el acceso real a las rutas.
LECCIÓN 10

Crear decoradores personalizados

Objetivo: Centralizar reglas de autorización reutilizables.

¿Qué aprenderás y por qué es importante?

Cuando varias vistas necesitan la misma regla, repetir condiciones en cada función produce código duplicado y aumenta el riesgo de errores. Un decorador personalizado envuelve una vista, comprueba una condición antes de ejecutarla y permite o rechaza el acceso. Puede servir para comprobar grupos, estados de cuenta o reglas específicas del proyecto.

Explicación técnica paso a paso

Un decorador recibe una función y devuelve otra función que la envuelve. functools.wraps conserva metadatos de la vista. En este ejemplo se exige autenticación y pertenencia a un grupo; si no se cumple la regla se devuelve HTTP 403, que significa acceso prohibido. Es importante diferenciarlo de 401 o de una redirección al login.

Ejemplo práctico · Python / Django
cuentas/decoradores.py y tienda/views.py
PYTHON
1# cuentas/decoradores.py
2from functools import wraps
3from django.contrib.auth.decorators import login_required
4from django.core.exceptions import PermissionDenied
5
6def grupo_requerido(nombre_grupo):
7 def decorador(vista):
8 @wraps(vista)
9 @login_required
10 def envoltura(request, *args, **kwargs):
11 if not request.user.groups.filter(name=nombre_grupo).exists():
12 raise PermissionDenied
13 return vista(request, *args, **kwargs)
14 return envoltura
15 return decorador
16
17# Uso en tienda/views.py
18from cuentas.decoradores import grupo_requerido
19
20@grupo_requerido('Administradores')
21def eliminar_producto(request, pk):
22 # Recuperar objeto y confirmar borrado mediante POST
23 ...
Ejemplo complementario · Comandos / HTML
Pruebas sugeridas
BASH
1# Pruebas sugeridas
2# 1. Usuario anónimo -> redirigido al login
3# 2. Usuario autenticado sin grupo -> 403
4# 3. Usuario del grupo -> accede a la vista
5# 4. Solicitud GET de eliminación -> solo confirma
Atención y buenas prácticas: En sistemas reales conviene priorizar permisos concretos frente a reglas rígidas por nombre de grupo cuando la organización tiene múltiples roles.
Actividad de aplicación: Crear un decorador que permita editar productos solo a usuarios del grupo Administradores y comprobar tres escenarios de acceso.

Ponte a prueba — Parte 2 (Seguridad)

Comprueba tu dominio de las lecciones 07 a 10 sobre authenticate, login, logout, @login_required, permisos y decoradores personalizados.

Ko-fi
Donaciones
Apoyá cafeycodigo con un café en Ko-fi. Colaboradores: insignia, muro y zona exclusiva.