Cómo agregar autenticación con Flask Login

- Andrés Cruz

In english
Cómo agregar autenticación con Flask Login

Puede usar el módulo Flask-Login para controlar el acceso. Proporciona administración de sesiones de usuario para Flask: iniciar sesión, cerrar sesión y recordar sesiones.

 Flask-Login permite:

  • Almacene la identificación del usuario activo en la sesión de Flask y le permitirá iniciar y cerrar sesión fácilmente.
  • Le permite restringir las vistas a los usuarios conectados (o desconectados). (Necesario iniciar sesión)
  • Manejar la funcionalidad "recuérdame", normalmente complicada.
  • Ayude a proteger las sesiones de sus usuarios para que no sean robadas por ladrones de cookies.

Sin embargo, no permitirá:

  • Imponerle una base de datos particular u otro método de almacenamiento. Usted está totalmente a cargo de cómo se carga el usuario.
  • Restringirle al uso de nombres de usuario y contraseñas, OpenID o cualquier otro método de autenticación.
  • Manejar permisos más allá de "iniciar sesión o no".
  • Gestionar el registro de usuarios o la recuperación de cuentas.

El ecosistema del Flask

Flask facilita la composición de aplicaciones ortogonales en una más grande y compleja de la misma manera que las funciones se componen en lenguajes funcionales. Tomemos, por ejemplo, una aplicación para almacenar mensajes como un foro, aunque en frameworks como Django, existen todo tipo de aplicaciones complejas que pudieras adaptar con mucho esfuerzo, en Flask, al utilizar extensiones como:

Flask-Admin para la gestión de bases de datos
Flask-Assets para la gestión de activos
Flask-DebugToolbar para depuración y creación de perfiles.
Flask-Markdown para publicaciones en el foro
Flask-Script para comandos básicos
Flask-Security para autenticación
Flask-SQLAlchemy para consultas de base de datos
Flask-WTF para formularios
Con una lista tan larga, es casi sorprendente que todas las aplicaciones puedan trabajar juntas sin crear dependencias entre sí (o, más bien, es increíble si vienes de Django), pero las extensiones de Flask suelen seguir la filosofía de Unix de “hacer una cosa bien”. Esto es excelente ya que, al no existir relaciones entre estas dependencias, puedes personalizar bastante tu desarrollo.

 

Veremos cómo usar Flask Login para tener un completo y básico sistema de Login en pocos momentos en nuestra aplicación.

Para seguir el tutorial tienes que tener en claro los siguientes aspectos:

  1. Manejar los espacios virtuales, para crear nuestra aplicación
  2. Conocer los primeros pasos con Flask 

Sobre Flask Login

Flask-Login es una extensión para el framework web de Flask que proporciona la gestión de las sesiones de usuario, como el inicio de sesión, el cierre de sesión o logout y la persistencia de la sesión. Para usar Flask-Login, creamos un modelo para el usuario que defina los métodos y parámetros requeridos por esta extensión, como is_authenticated, is_active e is_anonymous, y luego inicialice la extensión en su aplicación Flask.

Flask-Login es provisto mediante un paquete excelente que nos permite manejar las tareas comunes de iniciar y cerrar sesión, además de recordar las credenciales por un largo tiempo.

Trabaja de una manera sencilla en la cual necesitamos un modelo de usuarios y a raíz de este poder comparar credenciales e iniciar sesión:

Con nuestro usuario autenticado podemos realizar operaciones como:

  1. Cerrar sesión fácilmente.
  2. Restringir la vista a los usuarios conectados (o desconectados).

Instalar Flask Login

Con nuestra aplicación creada, vamos a instalar el paquete con:

pip install flask-login

Lo primero que necesitamos, es instalar el paquete, ya que como debes de saber en este punto, Flask es un micro framework y trae lo mínimo y necesario para funcionar; en esencia, funciones básicas del core, ruteo, seguridad y un motor de plantilla para HTML; para todo lo demás, existe Mastercard o instalar paquetes de terceros ya sea de Python o propios del framework.

Configurarlo en tu app

Vamos a ir a nuestro __init__ en proyect/app/:

from flask_login import LoginManager
login_manager = LoginManager()
login_manager.init_app(app)

Y con esto ya estamos listos para usarlo.

Vamos a tener un módulo o aplicación llamada app:

proyect/app/user en la cual crearemos el MVC tipico en las aplicaciones en Flask:

Controladores, views.py:

from flask import Blueprint,session, render_template, request, redirect, url_for, flash, get_flashed_messages
from app.user.models import User
from app.user.forms import LoginForm, RegisterForm
from app import db, login_manager
from flask_login import current_user,login_user, login_required, logout_user
from werkzeug.security import generate_password_hash
userBp = Blueprint('user',__name__)
@login_manager.user_loader
def load_user(user_id):
    return User.query.get(user_id)
@userBp.route('/login', methods=('GET', 'POST'))
def login():
   #print(current_user.name)
   form = LoginForm(meta={'csrf':False})
   if form.validate_on_submit():
      user = User.query.filter_by(username=form.username.data).first()
      if user and user.check_password(form.password.data):
         # registrar sesion
         login_user(user, remember=True)
         flash("Bienvenido de nuevo "+user.username)
         print("Vien")
         return redirect(url_for('chat.hello_world'))
      else:
         print("Malo")
         flash("Usuario o contraseña incorrectos",'danger')
   if form.errors:
      print(form.errors)
      flash(form.errors,'danger')
   return render_template('user/login.html',form=form)
@userBp.route('/logout')
@login_required
def logout():
   logout_user()
   return redirect(url_for('user.login'))
@userBp.route('/register', methods=('GET', 'POST'))
def register():
   print(session)
   print(current_user)
   form = RegisterForm(meta={'csrf':False})
   if form.validate_on_submit():
      if User.query.filter_by(username=form.username.data).first():
         flash("El usuario ya existe en el sistema",'danger')
      else:
         #crear usuario
         u = User()
         u.name = form.username.data
         u.username = form.username.data
         u.password = generate_password_hash(form.password.data)
         u.email = form.email.data
         login_user(u, remember=True)
         flash("Usuario creado con éxito")
         return redirect(url_for('user.register'))
   if form.errors:
      flash(form.errors,'danger')
   return render_template('user/register.html',form=form)
@login_required
def logout():
    logout_user()
    return redirect(url_for('user.login'))

Modelos models.py

from flask_login import UserMixin
from app import db
from werkzeug.security import check_password_hash,generate_password_hash
class User(db.Model,UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    email= db.Column(db.String(100), unique=True)
    username= db.Column(db.String(100), unique=True)
    password= db.Column(db.String(400))
    name= db.Column(db.String(100))
    #__tablename__ = 'users'
    def check_password(self, password):
        return check_password_hash(self.password,password)

Formularios forms.py

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, HiddenField
from wtforms.validators import InputRequired, EqualTo
class LoginForm(FlaskForm):
    username = StringField('Usuario', validators=[InputRequired()])
    password = PasswordField('Contraseña', validators=[InputRequired()])
class RegisterForm(FlaskForm):
    username = StringField('Usuario', validators=[InputRequired()])
    email = StringField('Email', validators=[InputRequired()])
    password = PasswordField('Contraseña', validators=[InputRequired(),EqualTo('confirm')])
    confirm  = PasswordField('Repetir Contraseña')

Templates

Templates iniciar sesión, /app/templates/user/login

<form action="{{ url_for('user.login') }}" method="POST">
    <div class="form-group">
        {{ form.username.label }} 
        {{ form.username(class="form-control") }}
    </div>
    <div class="form-group">
        {{ form.password.label }} 
        {{ form.password(class="form-control") }}
    </div>
    <input class="btn btn-success" type="submit" value="Enviar">
</form>

Templates registrar, /app/templates/user/register

<form action="{{ url_for('user.register') }}" method="POST">
    <div class="form-group">
        {{ form.username.label }} 
        {{ form.username(class="form-control") }}
    </div>
    
    <div class="form-group">
        {{ form.email.label }} 
        {{ form.email(class="form-control") }}
    </div>
    <div class="form-group">
        {{ form.password.label }} 
        {{ form.password(class="form-control") }}
    </div>
    <div class="form-group">
        {{ form.confirm.label }} 
        {{ form.confirm(class="form-control") }}
    </div>
    <input class="btn btn-success" type="submit" value="Enviar">
</form>

Este ejemplo define un modelo de usuario que tiene un atriburo ID tambien se define su vista y ruta para el inicio de sesión inicia sesión, registrarse entre otros; las rutas protegidas se definen mediante el decorador @login_required, que garantiza que solo los usuarios autenticados puedan acceder a la función. La ruta de cierre de sesión cierra la sesión del usuario y lo redirige a la página de inicio de sesión.

También puede personalizar el comportamiento de Flask-Login usando varias opciones de configuración, como puedes consultar en la documentación oficial.

Recuerda que el código fuente del proyecto lo puedes ver aquí:

https://github.com/libredesarrollo/curso-flask-socketio

O aquí:

https://github.com/libredesarrollo/curso-flask-base

 

Y recuerda que no estamos empleando estilos:

Form Login
Form Login

Recuerda que este material forma parte de mi curso y libro completo sobre flask.

Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz en Udemy

Acepto recibir anuncios de interes sobre este Blog.