Cómo realizar la autenticación de usuario con Flask-Login — CodesCode
Aprende sobre las características que ofrece Flask-Login y cómo utilizarlas para crear una función de inicio de sesión segura para tu aplicación web de Python.
En este artículo, analizaremos las diversas características que ofrece Flask-Login y cómo usarlas para crear una funcionalidad de inicio de sesión segura para tu aplicación web. Al final de este artículo, tendrás una buena comprensión de cómo usar Flask-Login para implementar autenticación segura de usuarios en tus aplicaciones Flask.
La autenticación es una parte importante de cualquier aplicación web que permite a los usuarios acceder a datos o recursos, ya que asegura que solo las personas adecuadas tengan acceso a información sensible. Esto también se puede lograr en Flask utilizando Flask-Login.
Flask-Login es una extensión en Flask con funciones que manejan el inicio de sesión y cierre de sesión de los usuarios, y realiza un seguimiento de los usuarios actuales en toda la aplicación. Esto facilita la implementación de autenticación y autorización en tus aplicaciones Flask.
- ¿Por qué usar Flask-Login?
- Requisitos previos
- Primeros pasos
- Creando un modelo de usuario
- Creando una base de datos
- Hashing de contraseñas
- Creando una vista de registro
- Creando una vista de inicio de sesión
- Creando lógica de cierre de sesión utilizando una vista protegida
- Agregando plantillas
- Cómo Flask-Login maneja las sesiones de usuario con cookies de sesión de usuario
- Conclusión
¿Por qué usar Flask-Login?
Flask-Login cuenta con varias características y funciones que facilitan la autenticación sin problemas en aplicaciones Flask. Aquí tienes algunos de los beneficios de usar Flask-Login:
-
Gestión de sesiones de usuario. Flask-Login maneja la creación y destrucción de sesiones de usuario. También puede almacenar el ID del usuario actual en la sesión para que puedas verificar fácilmente si un usuario ha iniciado sesión.
-
Funcionalidad de inicio de sesión y cierre de sesión. Flask-Login proporciona funciones integradas de inicio y cierre de sesión. Estas funciones se encargan de todos los procesos importantes, como la creación y destrucción de sesiones y la redirección del usuario a la página adecuada.
-
Callback de carga de usuario. Flask-Login te permite definir un callback de carga de usuario. Este callback se utiliza para cargar el objeto de usuario para la sesión actual. Esto es útil si estás utilizando una base de datos para almacenar información de usuario.
-
Autenticación y autorización. Flask-Login facilita la implementación de autenticación y autorización en tus aplicaciones. Puedes usar Flask-Login para proteger páginas o rutas específicas y otorgar diferentes niveles de acceso a los usuarios en tu aplicación.
Requisitos previos
Para seguir este artículo, necesitas lo siguiente:
- Conocimiento de Python y la sintaxis de Flask
- Conocimientos básicos de HTML y CSS
- Python versión 3 y Flask instalados
Obviamente, también necesitarás acceso a un navegador web.
Primeros pasos
Para aprovechar al máximo el módulo de inicio de sesión de Flask, necesitamos tener instalado Flask-Login y otras dependencias necesarias. Estas bibliotecas proporcionan las funciones y herramientas necesarias para mejorar la funcionalidad de tu aplicación. Para instalarlas, abre tu línea de comandos o terminal y ejecuta el siguiente comando pip:
pip install flask-login flask_sqlalchemy flask_bcrypt
Aquí tienes una descripción de para qué se utiliza cada una de estas bibliotecas:
- Flask-SQLAlchemy: integra SQLAlchemy con Flask para operaciones de base de datos
- Flask-Bcrypt: agrega hashing bcrypt para seguridad de contraseñas en Flask
Una vez completada la instalación, Flask login se descargará automáticamente en el directorio que utilizaste.
Nota: al momento de la escritura, hay un pequeño problema en la resolución de las dependencias en la última versión de Flask y Werkzeug. Para resolver esto, debes forzar la instalación de la versión 2.3.0 de Werkzeug, ya que es la única versión conocida que funciona correctamente en este momento.
Una vez instaladas tus dependencias, deberás inicializarlas con tu aplicación Flask:
from flask_sqlalchemy import SQLAlchemy
from flask_login import UserMixin, LoginManager, login_user, logout_user, login_required
from flask_bcrypt import Bcrypt
from flask_login import LoginManager
app = Flask(__name__)
login_manager = LoginManager()
login_manager.init_app(app)
En el fragmento de código anterior, también hemos inicializado el objeto LoginManager
en nuestra aplicación. LoginManager
es una extensión de Flask-Login que se utiliza para configurar las configuraciones necesarias para manejar las sesiones de usuario.
Creando un modelo de usuario
Un modelo es una representación de la estructura de datos que desea utilizar en su aplicación. Define cómo se organiza, almacena y manipula los datos dentro del sistema. Los modelos generalmente se usan con una base de datos que sigue la estructura definida previamente. Para nuestra aplicación, tenemos los siguientes datos:
- un ID único
- un nombre de usuario
- una contraseña (encriptada)
class User(UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), unique=True)
password_hash = db.Column(db.String(128))
def __repr__(self):
return f'<User {self.username}>'
También puede agregar propiedades adicionales a su modelo de usuario, como una dirección de correo electrónico o una foto de perfil, dependiendo del alcance de su proyecto.
Creando una base de datos
Una vez que haya definido su modelo de usuario, debe crear una base de datos que almacenará la estructura de datos que creamos en el modelo anterior.
Para este artículo, estaremos utilizando una base de datos SQLite. Esto se debe a que SQLite es un motor de base de datos liviano y sin servidor. Esto facilita su configuración y uso, ya que no requiere una instalación aparte. También es una buena opción para aplicaciones pequeñas a medianas.
Aquí hay una descripción de los pasos para usar una base de datos SQLite en nuestra aplicación:
-
Para utilizar la base de datos SQLite, debe establecer un URI en la configuración de su aplicación Flask. Esto generalmente se hace en la parte superior, junto con otras configuraciones. Aquí hay un fragmento que puede usar:
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db' # Usando SQLite como la base de datos
En este fragmento, el
///...
indica la ruta relativa a su archivo –site.db
– que es el nombre que usamos para nuestro archivo de base de datos SQLite. Este nombre se puede cambiar a cualquier cosa que prefiera. -
A continuación, debe inicializar el ORM Flask-SQLAlchemy usando este fragmento:
db = SQLAlchemy(app)
SQLAlchemy es un mapeador objeto-relacional que proporciona un conjunto de herramientas para trabajar con bases de datos utilizando Python. La línea
db = SQLAlchemy(app)
crea una instancia de la clase SQLAlchemy y la vincula a su aplicación Flask (app
). -
Para crear esta base de datos, debemos inicializar la base de datos usando el método
create_all
:if __name__ == '__main__': db.create_all() app.run(debug=True)
Este código se coloca típicamente al final de su script de Python o en un script separado dedicado a inicializar la base de datos. Una vez que ejecute su script, se creará el archivo de base de datos con las tablas correspondientes basadas en los modelos que definimos anteriormente.
En este caso, el código creará un archivo
site.db
con una tablaUser
si aún no existe. El archivosite.db
generalmente se encuentra en una carpeta llamada/instance/
.
A continuación, debemos crear un user_loader
que tome un ID de usuario y devuelva el objeto User
correspondiente. Aquí hay un ejemplo:
@login_manager.user_loader
def load_user(user_id):
return User.query.get(user_id)
Encriptación de contraseñas
La encriptación de contraseñas es una medida de seguridad que almacena la representación criptográfica de la contraseña del usuario antes de almacenarla en una base de datos. De esta manera, se vuelve más difícil obtener la contraseña real incluso cuando la seguridad de la aplicación se ha visto comprometida.
Por lo general, la contraseña se encripta primero en el proceso de registro y se almacena en una base de datos. Luego, cada vez que un usuario inicia sesión, su contraseña se vuelve a encriptar y se compara con la contraseña encriptada almacenada en la base de datos. Si las dos contraseñas coinciden, el usuario está autenticado y se le da acceso a la aplicación.
Cómo hashear y verificar contraseñas usando Flask-Bcrypt
Flask tiene una extensión llamada Flask-Bcrypt que ayuda a lograr esta funcionalidad. Tiene dos funciones principales: generate_password_hash()
y check_password_hash()
.
La función generate_password_hash()
toma la contraseña del usuario como argumento y devuelve una contraseña hasheada. Esto se usa generalmente en la lógica de registro.
La función check_password_hash()
toma una contraseña y una contraseña hasheada como argumentos y devuelve true
si las dos contraseñas coinciden, o false
si no coinciden. Esto se llama antes de otorgar acceso a la vista de inicio de sesión.
Creando una vista de registro
Vistas son una parte del framework Flask que se utiliza para generar HTML, JSON u otros datos que se envían al navegador del usuario. En este fragmento de código, vamos a crear una vista que reciba la entrada del usuario y agregue los detalles a la base de datos:
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
hashed_password = bcrypt.generate_password_hash(password).decode('utf-8')
new_user = User(username=username, password=hashed_password)
db.session.add(new_user)
db.session.commit()
return redirect(url_for('welcome'))
return render_template('registeration.html')
Desglose del código:
-
En la primera línea, definimos una ruta para la URL
/login
. Esta ruta acepta tanto solicitudes GET como POST. La funciónlogin()
, asociada con la ruta, se ejecutará cuando se realice una solicitud. -
Luego, confirmamos si el método de la solicitud es POST:
if request.method == 'POST':
Una vez confirmado, la función obtiene los valores ingresados por el usuario en el formulario de inicio de sesión:
username = request.form['username'] password = request.form['password']
-
Luego consulta la base de datos en busca de un usuario con el nombre de usuario proporcionado. Si se encuentra un usuario con el nombre de usuario proporcionado y la contraseña coincide, se ejecutará el código dentro de este bloque.
Creando una vista de inicio de sesión
En la vista de inicio de sesión, creamos una lógica que acepta la entrada desde una página y luego verifica si la entrada coincide con alguna fila en la base de datos:
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
user = User.query.filter_by(username=username).first()
if user and bcrypt.check_password_hash(user.password, password):
login_user(user)
return redirect(url_for('welcome'))
return render_template('login.html')
Desglose del código:
-
En la primera línea –
@app.route('/login', methods=['GET', 'POST']):
– estamos utilizando un decorador que define una ruta para la URL/login
. La ruta acepta tanto solicitudes GET como POST. La función asociada,login()
, se ejecutará cuando se realice una solicitud a esta ruta. -
La función
login()
comienza comprobando si el método de la solicitud es POST:if request.method == 'POST':
Una vez confirmado que es una solicitud POST, recupera los valores ingresados por el usuario en el formulario de inicio de sesión:
username = request.form['username'] password = request.form['password']
-
Luego consulta la base de datos en busca de un usuario con el nombre de usuario proporcionado:
user = User.query.filter_by(username=username).first() if user and bcrypt.check_password_hash(user.password, password):
-
Si tanto el nombre de usuario como la contraseña son validados, se le otorga acceso al usuario mediante las funciones
login_user
yredirect
de Flask-Login:login_user(user) redirect(url_for('welcome'))
-
Sin embargo, si el método de la
request
no es POST o los detalles son incorrectos, se renderiza la plantillalogin.html
:return render_template('login.html')
En resumen, verifica si las credenciales ingresadas son válidas, inicia sesión al usuario y lo redirige a la página de bienvenida si tiene éxito. Si el inicio de sesión no tiene éxito o es una solicitud GET, se renderiza la plantilla de inicio de sesión para que el usuario ingrese sus credenciales.
Creando la lógica de cierre de sesión utilizando una vista protegida
En la mayoría de las aplicaciones, algunas páginas son inaccesibles si el usuario no ha iniciado sesión. Esto incluye páginas como el historial de transacciones, borradores y páginas de cierre de sesión. Flask-Login proporciona una forma conveniente de proteger estas páginas/rutas y restringir el acceso a usuarios autenticados utilizando el decorador login_required
. Aquí tienes una explicación de cómo funciona.
Para utilizar esta funcionalidad, debes importar el decorador login_required
de Flask-Login:
from flask_login import login_required
A continuación, debes agregar el decorador login_required
a cualquier ruta que desees proteger. Por ejemplo, vamos a crear una página de cierre de sesión que solo se puede acceder cuando el usuario ha iniciado sesión:
@app.route('/logout') @login_required def logout(): logout_user() return redirect(url_for('login'))
Aquí tienes una explicación de cómo funciona:
-
Al igual que en la vista de inicio de sesión,
@app.route('/logout')
define una ruta para la URL/logout
. -
A continuación, agregamos un decorador
login_required
que asegura que el usuario debe haber iniciado sesión para acceder a la rutalogout
. Si un usuario no ha iniciado sesión e intenta acceder a esta ruta, será redirigido a la página de inicio de sesión. -
Dentro de la función
logout
, se llama alogout_user()
. Esta función es proporcionada por Flask-Login y se utiliza para cerrar la sesión del usuario actual. -
Después de cerrar la sesión del usuario, la función lo redirige a la ruta
login
utilizandoredirect(url_for('login'))
.
Entonces, cuando un usuario accede a la ruta /logout
, Flask-Login se asegura de que haya iniciado sesión (@login_required
), lo cierra la sesión y lo redirige a la página de inicio de sesión. Esto ayuda a manejar el cierre de sesión de manera segura en tu aplicación Flask. El decorador login_required
se aplica a la ruta /protected
, lo que indica que solo los usuarios autenticados pueden acceder. Y si un usuario intenta acceder a una página protegida sin haber iniciado sesión, Flask-Login lo redirigirá a la página de inicio de sesión.
Agregando plantillas
Las plantillas en Flask te permiten utilizar páginas HTML para definir cómo se verá tu sitio. Para implementar completamente la lógica en nuestro archivo app.py
, vamos a crear las siguientes páginas HTML:
A continuación, se muestra una animación que muestra cómo las plantillas representan las diferentes páginas de nuestro sitio:
https://player.vimeo.com/video/884411943
Puedes ver el código completo de este tutorial y obtener más información sobre su implementación en el repositorio de GitHub de este artículo.
Cómo Flask-Login maneja las sesiones de usuario con cookies de sesión de usuario
Una sesión de usuario es un sistema utilizado para realizar un seguimiento y actualizar la información del usuario mientras este ha iniciado sesión. Flask-Login administra estas sesiones almacenando una cookie de sesión en el navegador del usuario. La cookie de sesión es un pequeño fragmento de datos que contiene un identificador único para la sesión del usuario.
Cuando un usuario inicia sesión en un sitio web utilizando Flask-Login, el servidor genera una cookie de sesión y la envía al navegador del usuario. El navegador almacena la cookie de sesión y la incluye en todas las peticiones al servidor. El servidor utiliza la cookie de sesión para identificar al usuario y su estado de sesión.
Por ejemplo, si el usuario ha iniciado sesión y visita una página protegida por Flask-Login, Flask-Login verifica la cookie de sesión para ver si el usuario está autenticado. Si el usuario está autenticado, Flask-Login cargará la información del perfil del usuario desde la base de datos y la pondrá a disposición de la vista. Si el usuario no está autenticado, Flask-Login redirigirá al usuario a la página de inicio de sesión.
Cuando el usuario cierra sesión en el sitio web, el servidor elimina la cookie de sesión del navegador del usuario, lo que termina la sesión del usuario.
Conclusión
Flask ofrece una variedad de funciones que abordan diferentes aspectos de la autenticación, desde la gestión de la sesión del usuario hasta la autorización. Al utilizar estas funciones, puedes implementar un sistema de autenticación robusto y seguro adaptado a las necesidades específicas de tu aplicación.
Leave a Reply