Cómo añadir autenticación a su aplicación con Flask-Login

Introducción

Permitir a los usuarios iniciar sesión en su aplicación es una de las funciones más frecuentes que añadirá a su aplicación web. Este artículo explicará cómo añadir autenticación a su aplicación Flask con el paquete Flask-Login.

Gif animado de la aplicación Flask y cuadro de inicio de sesión

Crearemos algunas páginas de registro e inicio de sesión que permiten a los usuarios iniciar sesión y acceder a páginas protegidas que los usuarios que no hayan iniciado sesión no pueden ver. Obtendremos información del modelo de usuario y la mostraremos en nuestras páginas protegidas cuando el usuario inicie sesión para simular el aspecto que tendrá un perfil.

En este artículo, explicaremos lo siguiente:

  • Usar la biblioteca de Flask-Login para la administración de las sesiones
  • Usar la utilidad Flask integrada para autenticar contraseñas
  • Añadir páginas protegidas a nuestra aplicación solo para los usuarios con sesión iniciada
  • Usar Flask-SQLAlchemy para crear un modelo de usuario
  • Crear formularios de registro e inicio de sesión para que nuestros usuarios creen cuentas e inicien sesión
  • Devolver mensajes intermitentes de error a los usuarios cuando algo falle
  • Usar la información de la cuenta del usuario para mostrarla en la página de perfil

El código fuente para este proyecto está disponible en GitHub.

Requisitos previos

Para completar este tutorial, necesitará lo siguiente:

  • Phython instalado en un entorno local.
  • Tener conocimiento de la gestión de archivos y navegación básicas de Linux es útil, pero no obligatorio.
  • Estar familiarizado con un editor como Visual Studio Code es útil, pero no obligatorio.

Nuestra aplicación usará el patrón de fábrica de aplicación Flask con modelos. Tendremos un modelo para gestionar todo lo relacionado con la autenticación, y otro para nuestras rutas regulares, que incluyen el índice y la página de perfil protegida. En una aplicación real, puede desglosar la funcionalidad de cualquier forma que quiera, pero la solución explicada aquí funcionará bien para este tutorial.

Aquí, tiene un diagrama que muestra cómo se verá la estructura de archivos de su proyecto una vez que haya completado el tutorial:

. └── flask_auth_app     └── project         ├── __init__.py       # setup our app         ├── auth.py           # the auth routes for our app         ├── db.sqlite         # our database         ├── main.py           # the non-auth routes for our app         ├── models.py         # our user model         └── templates             ├── base.html     # contains common layout and links             ├── index.html    # show the home page             ├── login.html    # show the login form             ├── profile.html  # show the profile page             └── signup.html   # show the signup form 

A medida que avancemos en el tutorial, crearemos estos directorios y archivos.

Paso 1: Instalar paquetes

Estos son los tres paquetes principales que necesitamos para nuestro proyecto:

  • Flask
  • Flask-Login: para administrar las sesiones del usuario tras la autenticación
  • Flask-SQLAlchemy: para representar el modelo de usuario y la interfaz con nuestra base de datos

Usaremos SQLite para evitar tener que instalar dependencias adicionales para la base de datos.

Primero, empezaremos por crear el directorio del proyecto:

  • mkdir flask_auth_app

A continuación, debemos navegar al directorio del proyecto:

  • cd flask_auth_app

Querrá crear un entorno Python si no tiene uno. Dependiendo de cómo se instaló Python en su equipo, sus comandos tendrán un aspecto similar a:

  • python3 -m venv auth
  • source auth/bin/activate

Nota: Puede consultar el tutorial relevante a su entorno local para configurar venv.

Ejecute los siguientes comandos desde su entorno virtual para instalar los paquetes necesarios:

  • pip install flask flask-sqlalchemy flask-login

Ahora que instaló los paquetes, está listo para crear el principal archivo de la aplicación.

Paso 2: Crear el archivo principal de la aplicación

Empezaremos creando un directorio project:

  • mkdir project

El primer archivo en el que trabajaremos será el archivo __init__.py para nuestro proyecto:

  • nano project/__init__.py

Este archivo tendrá la función de crear nuestra aplicación, que iniciará la base de datos y registrará nuestros modelos. En este momento, esto no hará mucho, pero será necesario para el resto de nuestra aplicación. Debemos iniciar SQLAlchemy, establecer algunos valores de configuración y registrar nuestros modelos aquí.

project/__init__.py

from flask import Flask from flask_sqlalchemy import SQLAlchemy  # init SQLAlchemy so we can use it later in our models db = SQLAlchemy()  def create_app():     app = Flask(__name__)      app.config['SECRET_KEY'] = 'secret-key-goes-here'     app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'      db.init_app(app)      # blueprint for auth routes in our app     from .auth import auth as auth_blueprint     app.register_blueprint(auth_blueprint)      # blueprint for non-auth parts of app     from .main import main as main_blueprint     app.register_blueprint(main_blueprint)      return app 

Ahora que tenemos el archivo principal de la aplicación, podemos comenzar a añadir nuestras rutas.

Paso 3: Añadir rutas

Para nuestras rutas, usaremos dos modelos. Para nuestro modelo principal, tendremos una página principal (/) y una página de perfil (/profile) para cuando iniciemos sesión. Si el usuario intenta acceder a la página de perfil sin iniciar sesión, se lo enviará a la ruta de inicio de sesión.

Para nuestro modelo de autenticación, tendremos rutas para recuperar la página de inicio de sesión (/login) y la página de registro (/sign-up). También tendremos rutas para gestionar las solicitudes POST desde ambas rutas. Finalmente, tendremos una ruta para cerrar sesión (/logout) para cerrar la sesión de un usuario activo.

Por el momento, definiremos login, signup y logout con retornos simples. Los repasaremos más adelante y los actualizaremos con la funcionalidad deseada.

Primero, cree main.py para su main_blueprint:

  • nano project/main.py

project/main.py

from flask import Blueprint from . import db  main = Blueprint('main', __name__)  @main.route('/') def index():     return 'Index'  @main.route('/profile') def profile():     return 'Profile' 

A continuación, cree auth.py para su auth_blueprint:

  • nano project/auth.py

project/auth.py

from flask import Blueprint from . import db  auth = Blueprint('auth', __name__)  @auth.route('/login') def login():     return 'Login'  @auth.route('/signup') def signup():     return 'Signup'  @auth.route('/logout') def logout():     return 'Logout' 

En un terminal, puede configurar los valores FLASK_APP y FLASK_DEBUG:

  • export FLASK_APP=project
  • export FLASK_DEBUG=1

La variable de entorno FLASK_APP indica a Flask cómo cargar la aplicación. Debería apuntar hacia donde está create_app. Para nuestros fines, apuntaremos al directorio project.

La variable de entorno FLASK_DEBUG se habilita configurándola en 1. Esto habilitará un depurador que mostrará los errores de la aplicación en el navegador.

Asegúrese de que está en el directorio flask_auth_app y, a continuación, ejecute el proyecto:

  • flask run

Ahora, en un navegador web, debería poder navegar a las cinco URL posibles y ver el texto devuelto que se definió en auth.py y main.py.

Por ejemplo, visitar localhost:5000/profile muestra: Profile:

Captura de pantalla del proyecto en el puerto localhost 5000 en el navegador

Ahora que ya verificamos que nuestras rutas se comportan como se espera, podemos crear las plantillas.

Paso 4: Crear plantillas

Ahora crearemos las plantillas usadas en nuestra aplicación. Este es el primer paso antes de poder implementar la funcionalidad real de inicio de sesión. Nuestra aplicación usará cuatro plantillas:

  • index.html
  • profile.html
  • login.html
  • signup.html

También tendremos una plantilla base que tendrá un código común para cada una de las páginas. En este caso, la plantilla base tendrá enlaces de navegación y el diseño general de la página. Vamos a crearlas ahora.

Primero, cree un directorio templates en el directorio project:

  • mkdir -p project/templates

A continuación, cree base.html:

  • nano project/templates/base.html

A continuación, añada el siguiente código al archivo base.html:

project/templates/base.html

<!DOCTYPE html> <html>  <head>     <meta charset="utf-8">     <meta http-equiv="X-UA-Compatible" content="IE=edge">     <meta name="viewport" content="width=device-width, initial-scale=1">     <title>Flask Auth Example</title>     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css" /> </head>  <body>     <section class="hero is-primary is-fullheight">          <div class="hero-head">             <nav class="navbar">                 <div class="container">                      <div id="navbarMenuHeroA" class="navbar-menu">                         <div class="navbar-end">                             <a href="{{ url_for('main.index') }}" class="navbar-item">                                 Home                             </a>                             <a href="{{ url_for('main.profile') }}" class="navbar-item">                                 Profile                             </a>                             <a href="{{ url_for('auth.login') }}" class="navbar-item">                                 Login                             </a>                             <a href="{{ url_for('auth.signup') }}" class="navbar-item">                                 Sign Up                             </a>                             <a href="{{ url_for('auth.logout') }}" class="navbar-item">                                 Logout                             </a>                         </div>                     </div>                 </div>             </nav>         </div>          <div class="hero-body">             <div class="container has-text-centered">                {% block content %}                {% endblock %}             </div>         </div>     </section> </body>  </html> 

Este código creará una serie de enlaces de menú a cada página de la aplicación y un área donde aparecerá el contenido.

Nota: En segundo plano, estamos usando Bulma para gestionar el estilo y la distribución. Para aprender más sobre Bluma, considere leer la documentación oficial de Bulma.

A continuación, cree templates/index.html:

  • nano project/templates/index.html

Añada el siguiente código al archivo recién creado para añadir contenido a la página:

project/templates/index.html

{% extends "base.html" %}  {% block content %} <h1 class="title">   Flask Login Example </h1> <h2 class="subtitle">   Easy authentication and authorization in Flask. </h2> {% endblock %} 

Este código creará una página de índice básica con un título y un subtítulo.

A continuación, cree templates/login.html:

  • nano project/templates/login.html

Este código genera una página de inicio con campos para Correo electrónico y Contraseña. También hay una casilla de verificación para “recordar” una sesión iniciada.

project/templates/login.html

{% extends "base.html" %}  {% block content %} <div class="column is-4 is-offset-4">     <h3 class="title">Login</h3>     <div class="box">         <form method="POST" action="/login">             <div class="field">                 <div class="control">                     <input class="input is-large" type="email" name="email" placeholder="Your Email" autofocus="">                 </div>             </div>              <div class="field">                 <div class="control">                     <input class="input is-large" type="password" name="password" placeholder="Your Password">                 </div>             </div>             <div class="field">                 <label class="checkbox">                     <input type="checkbox">                     Remember me                 </label>             </div>             <button class="button is-block is-info is-large is-fullwidth">Login</button>         </form>     </div> </div> {% endblock %} 

A continuación, cree templates/signup.html:

  • nano project/templates/signup.html

Añada el siguiente código para crear una página de registro con campos para correo electrónico, nombre y contraseña:

project/templates/signup.html

{% extends "base.html" %}  {% block content %} <div class="column is-4 is-offset-4">     <h3 class="title">Sign Up</h3>     <div class="box">         <form method="POST" action="/signup">             <div class="field">                 <div class="control">                     <input class="input is-large" type="email" name="email" placeholder="Email" autofocus="">                 </div>             </div>              <div class="field">                 <div class="control">                     <input class="input is-large" type="text" name="name" placeholder="Name" autofocus="">                 </div>             </div>              <div class="field">                 <div class="control">                     <input class="input is-large" type="password" name="password" placeholder="Password">                 </div>             </div>              <button class="button is-block is-info is-large is-fullwidth">Sign Up</button>         </form>     </div> </div> {% endblock %} 

A continuación, cree templates/profile.html:

  • nano project/templates/profile.html

Añada este código para crear una página sencilla con un título codificado de forma rígida para darle la bienvenida a Anthony:

project/templates/profile.html

{% extends "base.html" %}  {% block content %} <h1 class="title">   Welcome, Anthony! </h1> {% endblock %} 

Más adelante, añadiremos un código para saludar dinámicamente a cualquier usuario.

Una vez que haya añadido las plantillas, podremos actualizar las instrucciones de retorno en cada una de las rutas que tenemos para que devuelvan las plantillas en vez del texto.

A continuación, actualice main.py modificando la línea de importación y las rutas para index y profile:

project/main.py

from flask import Blueprint, render_template ... @main.route('/') def index():     return render_template('index.html')  @main.route('/profile') def profile():     return render_template('profile.html') 

Ahora, actualizará auth.py modificando la línea de importación y las rutas para login y signup:

project/auth.py

from flask import Blueprint, render_template ... @auth.route('/login') def login():     return render_template('login.html')  @auth.route('/signup') def signup():     return render_template('signup.html') 

Una vez que haya realizado estos cambios, así lucirá la página de registro si navega a /sign-up:

Página de registro en /signup

También debería poder ver las páginas para /, /login y /profile.

No trabajaremos con /logout por ahora porque no mostrará una plantilla cuando esté listo.

Paso 5: Crear modelos de usuario

Nuestro modelo de usuario representa qué significa para nuestra aplicación tener un usuario. Tendremos campos para una dirección de correo electrónico, contraseña y nombre. En su aplicación, puede decidir que quiere guardar mucha más información por usuario. Puede añadir cosas como fecha de nacimiento, perfil, imagen, ubicación o cualquier preferencia del usuario.

Los modelos creados en Flask-SQLAlchemy se representan mediante clases y, luego, se trasladan a tablas en una base de datos. Los atributos de esas clases se convierten en columnas para esas tablas.

Ahora crearemos ese modelo de usuario:

  • nano project/models.py

Este código crea un modelo de usuario con columnas para id, email, password y name:

project/models.py

from . import db  class User(db.Model):     id = db.Column(db.Integer, primary_key=True) # primary keys are required by SQLAlchemy     email = db.Column(db.String(100), unique=True)     password = db.Column(db.String(100))     name = db.Column(db.String(1000)) 

Ahora que creó un modelo de usuario, puede configurar su base de datos.

Paso 6: Configurar la base de datos

Como se indicó en los requisitos previos, usaremos una base de datos SQLite. Podríamos crear una base de datos SQLite por nuestra cuenta, pero dejemos que Flask-SQLAlchemy lo haga por nosotros. Ya tenemos la ruta de la base de datos especificada en el archivo __init__.py, así que solo necesitamos indicar a Flask-SQLAlchemy que cree la base de datos en el REPL de Python.

Si detiene su aplicación y abre un REPL de Python, podemos crear la base de datos usando el método create_all en el objeto db. Asegúrese de que aún está en el entorno virtual y en el directorio flask_auth_app.

  • from project import db, create_app
  • db.create_all(app=create_app()) # pass the create_app result so Flask-SQLAlchemy gets the configuration.

Nota: Si el uso del intérprete de Python es nuevo para usted, puede consultar la documentación oficial.

Ahora, verá un archivo db.sqlite en el directorio de su proyecto. Esta base de datos contendrá nuestra tabla de usuario.

Paso 7: Configurar la función de autorización

Para nuestra función de registro, tomaremos los datos que escriba el usuario en el formulario y los añadiremos a nuestra base de datos. Antes de añadirlo, debemos asegurarnos de que el usuario no existe ya en la base de datos. Si no es así, debemos asegurarnos de autenticar la contraseña antes de colocarla en la base de datos, porque no queremos que nuestras contraseñas se almacenen en archivo de texto.

Empezaremos por añadir una segunda función para gestionar los datos del formulario POST. En esta función, recopilaremos primero los datos ingresados por el usuario.

Cree la función y añada una redirección en la parte inferior. Esto proporcionará una experiencia de usuario de un registro correcto y se lo redirigirá a la página de inicio de sesión.

Actualice auth.py modificando la línea de importación e implementando signup_post:

project/auth.py

from flask import Blueprint, render_template, redirect, url_for ... @auth.route('/signup', methods=['POST']) def signup_post():     # code to validate and add user to database goes here     return redirect(url_for('auth.login')) 

Ahora, añadiremos el resto del código necesario para registrar a un usuario.

Para comenzar, tendremos que usar el objeto de solicitud para obtener los datos del formulario.

Continúe para actualizar auth.py añadiendo importaciones e implementando signup_post:

auth.py

from flask import Blueprint, render_template, redirect, url_for, request from werkzeug.security import generate_password_hash, check_password_hash from .models import User from . import db ... @auth.route('/signup', methods=['POST']) def signup_post():     email = request.form.get('email')     name = request.form.get('name')     password = request.form.get('password')      user = User.query.filter_by(email=email).first() # if this returns a user, then the email already exists in database      if user: # if a user is found, we want to redirect back to signup page so user can try again         return redirect(url_for('auth.signup'))      # create a new user with the form data. Hash the password so the plaintext version isn't saved.     new_user = User(email=email, name=name, password=generate_password_hash(password, method='sha256'))      # add the new user to the database     db.session.add(new_user)     db.session.commit()      return redirect(url_for('auth.login')) 

Nota: El almacenamiento de contraseñas en archivos de texto se considera una mala práctica de seguridad. Normalmente, querrá usar un algoritmo de autenticación complejo y una sal de contraseña para proteger las contraseñas.

Paso 8: Probar el método de registro

Ahora que tenemos el método de registro, deberíamos poder crear un nuevo usuario. Use el formulario para crear un usuario.

Hay dos formas de verificar si el registro funcionó: puede usar un visor de base de datos para ver la fila que se añadió a su tabla o puede intentar registrarse con la misma dirección de correo de nuevo y, si recibe un error, sabe que el primer correo electrónico se guardó correctamente. Hagamos eso.

Podemos añadir un código para permitir al usuario saber que el correo electrónico ya existe e indicarle que vaya a la página de inicio de sesión. Al invocar la función flash, enviaremos un mensaje a la siguiente solicitud que, en este caso, es la redirección. La página a la que llegamos tendrá acceso a ese mensaje en la plantilla.

Primero, añadimos flash antes de redirigir a nuestra página de registro.

project/auth.py

from flask import Blueprint, render_template, redirect, url_for, request, flash ... @auth.route('/signup', methods=['POST']) def signup_post():     ...     if user: # if a user is found, we want to redirect back to signup page so user can try again         flash('Email address already exists')         return redirect(url_for('auth.signup')) 

Para obtener el mensaje intermitente en la plantilla, podemos añadir este código sobre el formulario. Esto mostrará el mensaje directamente arriba del formulario.

project/templates/signup.html

... {% with messages = get_flashed_messages() %} {% if messages %}     <div class="notification is-danger">         {{ messages[0] }}. Go to <a href="{{ url_for('auth.login') }}">login page</a>.     </div> {% endif %} {% endwith %} <form method="POST" action="/signup"> 

Cuadro de registro mostrando el mensaje "El correo electrónico ya existe. Vaya a la página de inicio de sesión" en un cuadro rosa oscuro

Paso 9: Añadir el método de inicio de sesión

El método de inicio de sesión es similar a la función de registro porque tomaremos la información del usuario y haremos algo con ella. En este caso, compararemos la dirección de correo electrónico introducida para ver si está en la base de datos. Si es así, probaremos la contraseña proporcionada por el usuario autenticando la contraseña que el usuario introduce y comparándola con la contraseña autenticada en la base de datos. Sabemos que el usuario introdujo la contraseña correcta cuando ambas contraseñas autenticadas coinciden.

Una vez que el usuario haya pasado la comprobación de contraseña, sabemos que tiene las credenciales correctas y puede iniciar sesión usando Flask-Login. Al invocar login_user, Flask-Login creará una sesión para ese usuario que persistirá mientras el usuario permanezca con sesión iniciada, lo que permitirá al usuario ver las páginas protegidas.

Podemos comenzar con una nueva ruta para gestionar los datos que ya fueron procesados por POST. Redirigiremos a la página de perfil cuando el usuario inicie sesión correctamente.

project/auth.py

... @auth.route('/login', methods=['POST']) def login_post():     # login code goes here     return redirect(url_for('main.profile')) 

Ahora, debemos verificar si el usuario tiene las credenciales correctas:

project/auth.py

... @auth.route('/login', methods=['POST']) def login_post():     email = request.form.get('email')     password = request.form.get('password')     remember = True if request.form.get('remember') else False      user = User.query.filter_by(email=email).first()      # check if the user actually exists     # take the user-supplied password, hash it, and compare it to the hashed password in the database     if not user or not check_password_hash(user.password, password):         flash('Please check your login details and try again.')         return redirect(url_for('auth.login')) # if the user doesn't exist or password is wrong, reload the page      # if the above check passes, then we know the user has the right credentials     return redirect(url_for('main.profile')) 

Añadiremos el bloque en la plantilla para que el usuario pueda ver el mensaje intermitente. Al igual que con el formulario de registro, añadiremos el potencial mensaje de error directamente arriba del formulario:

project/templates/login.html

... {% with messages = get_flashed_messages() %} {% if messages %}     <div class="notification is-danger">         {{ messages[0] }}     </div> {% endif %} {% endwith %} <form method="POST" action="/login"> 

Ahora podemos decir que un usuario inició sesión correctamente, pero no tenemos nada para registrar la información del usuario. Aquí es donde traemos a Flask-Login para gestionar las sesiones de usuario.

Antes de comenzar, necesitamos algunas cosas para que Flask-Login funcione. Comience añadiendo UserMixin a su modelo de usuario. El UserMixin añadirá atributos de Flask-Login al modelo de forma que Flask-Login pueda trabajar con él.

models.py

from flask_login import UserMixin from . import db  class User(UserMixin, db.Model):     id = db.Column(db.Integer, primary_key=True) # primary keys are required by SQLAlchemy     email = db.Column(db.String(100), unique=True)     password = db.Column(db.String(100))     name = db.Column(db.String(1000)) 

A continuación, necesitamos especificar nuestro cargador de usuario. Un cargador de usuario indica a Flask-Login cómo encontrar un usuario específico a partir del identificador que se almacena en su cookie de sesión. Podemos añadir esto en nuestra función create_app junto con el código init para Flask-Login:

project/__init__.py

... from flask_login import LoginManager ... def create_app():     ...     db.init_app(app)      login_manager = LoginManager()     login_manager.login_view = 'auth.login'     login_manager.init_app(app)      from .models import User      @login_manager.user_loader     def load_user(user_id):         # since the user_id is just the primary key of our user table, use it in the query for the user         return User.query.get(int(user_id)) 

Finalmente, podemos añadir la función login_user justo antes de redirigir a la página de perfil para crear la sesión:

project/auth.py

from flask_login import login_user from .models import User ... @auth.route('/login', methods=['POST']) def login_post():     ...     # if the above check passes, then we know the user has the right credentials     login_user(user, remember=remember)     return redirect(url_for('main.profile')) 

Con la configuración de Flask-Login, podemos usar la ruta /login. Cuando todo esté listo, verá la página de perfil.

Página de perfil con "¡Bienvenido, Anthony!"

Paso 10: Proteger las páginas

Si su nombre no es Anthony, verá que el nombre está mal. Lo que queremos es que el perfil muestre el nombre en la base de datos. Primero debemos proteger la página y, luego, acceder a los datos del usuario para obtener el nombre.

Para proteger una página cuando se usa Flask-Login, añadiremos el decorador @login_required entre la ruta y la función. Esto evitará que un usuario que no haya iniciado sesión vea la ruta. Si el usuario no inició sesión, se lo redirigirá a la página de inicio, según la configuración de Flask-Login.

Con las rutas representadas con el decorador @login_required, tenemos la capacidad de usar el objeto current_user dentro de la función. Este current_user representa al usuario de la base de datos, y podemos acceder a todos los atributos de ese usuario con notación por puntos. Por ejemplo, current_user.email, current_user.password y current_user.name y current_user.id devolverán los valores reales almacenados en la base de datos para el usuario con sesión iniciada.

Usaremos el nombre del usuario actual y lo enviaremos a la plantilla. Usaremos ese nombre y mostraremos su valor.

project/main.py

from flask_login import login_required, current_user ... @main.route('/profile') @login_required def profile():     return render_template('profile.html', name=current_user.name) 

A continuación, en el archivo profile.html, actualice la página para mostrar el valor name:

project/templates/profile.html

... <h1 class="title">   Welcome, {{ name }}! </h1> 

Cuando vayamos a nuestra página de perfil, veremos que aparece el nombre del usuario.

Página de bienvenida del usuario con el nombre del usuario con sesión iniciada actualmente

Lo último que podemos hacer es actualizar la vista de cierre de sesión. Podemos invocar la función logout_user para cerrar sesión. Tenemos el decorador @login_required porque no tiene sentido que un usuario cierre una sesión que no inició en primer lugar.

project/auth.py

from flask_login import login_user, logout_user, login_required ... @auth.route('/logout') @login_required def logout():     logout_user()     return redirect(url_for('main.index')) 

Tras cerrar sesión e intentar ver la página del perfil, vemos que aparece un mensaje de error. Esto es porque Flask-Login muestra un mensaje intermitente para nosotros cuando el usuario no tiene permiso para acceder a una página.

Página de inicio con un mensaje que muestra que el usuario debe iniciar sesión para acceder a la página

Una última cosa que podemos hacer es poner declaraciones if en las plantillas para mostrar solo los enlaces relevantes al usuario. Antes de que el usuario inicie sesión, tendrá la opción de iniciar sesión o registrarse. Tras haber iniciado sesión, el usuario puede ir a su perfil o cerrar sesión:

templates/base.html

... <div class="navbar-end">     <a href="{{ url_for('main.index') }}" class="navbar-item">         Home     </a>     {% if current_user.is_authenticated %}     <a href="{{ url_for('main.profile') }}" class="navbar-item">         Profile     </a>     {% endif %}     {% if not current_user.is_authenticated %}     <a href="{{ url_for('auth.login') }}" class="navbar-item">         Login     </a>     <a href="{{ url_for('auth.signup') }}" class="navbar-item">         Sign Up     </a>     {% endif %}     {% if current_user.is_authenticated %}     <a href="{{ url_for('auth.logout') }}" class="navbar-item">         Logout     </a>     {% endif %} </div> 

Página de inicio con la navegación de las páginas Principal, Inicio de sesión y Registro en la parte superior de la pantalla

Con eso, creó correctamente su aplicación con autenticación.

Conclusión

Usamos Flask-Login y Flask-SQLAlchemy para crear un sistema de inicio de sesión para nuestra aplicación. Vimos cómo autenticar a un usuario creando primero un modelo de usuario y almacenando la información del usuario. A continuación, tuvimos que verificar que la contraseña del usuario fuera correcta autenticando la contraseña desde el formulario y comparándola con la almacenada en la base de datos. Finalmente, añadimos autorización a nuestra aplicación usando el decorador @login_required en una página de perfil de forma que solo los usuarios con sesión iniciada puedan verla.

Lo que creamos en este tutorial será suficiente para aplicaciones más pequeñas pero, si quiere tener más funcionalidad desde el principio, quizá desee considerar usar las bibliotecas Flask-User o Flask-Security, que se desarrollaron a partir de la biblioteca Flask-Login.