sql >> Base de Datos >  >> RDS >> Mysql

Crear una aplicación web desde cero usando Python Flask y MySQL:Parte 2

En la parte anterior de esta serie, vimos cómo comenzar con Python Flask y MySQL e implementar la parte de registro de usuarios de nuestra aplicación. En este tutorial, llevaremos esto al siguiente nivel implementando la funcionalidad de inicio y cierre de sesión para nuestra aplicación.

Cómo empezar

Primero clona el código fuente del tutorial anterior de GitHub.

git clone https://github.com/tutsplus/create-a-web-app-from-scratch-using-python-flask-and-mysql/.git

Una vez que se haya clonado el código fuente, vaya a la parte 1 directorio e inicie el servidor.

python app.py

Apunte su navegador a https://localhost:5000 y debería tener la aplicación ejecutándose.

Creación de la interfaz de inicio de sesión

Vaya a FlaskApp/templates y crea un nuevo archivo llamado signin.html . Abra signin.html y agregue el siguiente código HTML:

<!DOCTYPE html>
<html lang="en">
    <head>
		    
		<title>Python Flask Bucket List App - Sign In</title>
		    
		<link
			href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
			rel="stylesheet"
			integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
			crossorigin="anonymous"
		/>
		<link href="../static/signup.css" rel="stylesheet" />
	</head>

	<body>
		    
		<div class="container">
			        
			<div class="header">
				            
				<nav
					class="border-bottom flex-wrap mb-4 py-3 d-flex justify-content-center"
				>
					<a
						href="/"
						class="text-dark text-decoration-none mb-3 mb-md-0 d-flex align-items-center me-md-auto"
					>
						<span class="fs-4">Python Flask App</span>
					</a>

					<ul class="nav nav-pills">
						<li class="nav-item">
							<a href="/" class="nav-link">Home</a>
						</li>
						<li class="nav-item">
							<a href="/signup" class="nav-link">Signup</a>
						</li>
						<li class="nav-item">
							<a href="/signin" class="nav-link active" aria-current="page"
								>Sign In</a
							>
						</li>
					</ul>
					                        
				</nav>
				        
			</div>
			<div class="bg-light rounded-3 mb-4 p-5">
				<div class="container-fluid py-5">
					<h1 class="text-center fw-bold display-5">Bucket List App</h1>
					<form class="form-signin" action="/api/validateLogin" method="post">
                        <label for="inputEmail" class="sr-only">Email address</label>
                        <input type="email" name="inputEmail" id="inputEmail" class="form-control" placeholder="Email address" required autofocus>
                        <label for="inputPassword" class="sr-only">Password</label>
                        <input type="password" name="inputPassword" id="inputPassword" class="form-control" placeholder="Password" required>

                        <button id="btnSignIn" class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
                    </form>
			</div>
			        
			<footer class="footer">
				            
				<p>&copy; Company 2022</p>
				        
			</footer>

			    
		</div>

	</body>
</html>

Abra app.py y agregue una nueva ruta para la interfaz de inicio de sesión.

@app.route('/signin')
def showSignin():
    return render_template('signin.html')

A continuación, abra index.html y registro.html y agrega el href enlace para iniciar sesión en ambas páginas como /signin . Guarde todos los cambios y reinicie el servidor.

python app.py

Apunte su navegador a http://localhost:5000 y haga clic en Iniciar sesión y debería poder ver la página de inicio de sesión.

Implementación del inicio de sesión

Ahora, necesitamos crear una función para validar el inicio de sesión del usuario. Al hacer clic en Iniciar sesión , publicaremos la dirección de correo electrónico y la contraseña ingresados ​​en la función de validación de usuario.

Creación de un procedimiento almacenado

Para validar un usuario, necesitaremos un procedimiento almacenado de MySQL. Así que cree un procedimiento almacenado de MySQL como se muestra:

DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_validateLogin`(
IN p_username VARCHAR(20)
)
BEGIN
    select * from tbl_user where user_username = p_username;
END$$
DELIMITER ;

Obtendremos los detalles del usuario según el username desde la base de datos MySQL usando sp_validateLogin . Una vez que tengamos la contraseña codificada, la validaremos contra la contraseña ingresada por el usuario.

Validar el método de usuario

Cree un método para validar al usuario al que llamaremos cuando el usuario envíe el formulario:

@app.route('/api/validateLogin',methods=['POST'])
def validateLogin():
    try:
        _username = request.form['inputEmail']
        _password = request.form['inputPassword']

    except Exception as e:
        return render_template('error.html',error = str(e))

Como se ve en el código anterior, hemos leído la dirección de correo electrónico y la contraseña publicadas en _username y _password . Ahora llamaremos al sp_validateLogin procedimiento con el parámetro _username . Así que crea una conexión MySQL dentro de validatelogin método:

con = mysql.connect()

Una vez creada la conexión, crea un cursor usando el con conexión.

cursor = con.cursor()

Usando el cursor, llame al procedimiento almacenado de MySQL como se muestra:

cursor.callproc('sp_validateLogin',(_username,))

Obtenga los registros obtenidos del cursor como se muestra:

data = cursor.fetchall()

Si los datos tienen algunos registros, cotejaremos la contraseña recuperada con la contraseña ingresada por el usuario.

if len(data) > 0:
    if check_password_hash(str(data[0][3]),_password):
        return redirect('/userhome')
    else:
        return render_template('error.html',error = 'Wrong Email address or Password.')
else:
    return render_template('error.html',error = 'Wrong Email address or Password.')

Como se ve en el código anterior, hemos usado un método llamado check_password_hash para verificar si la contraseña hash devuelta coincide con la contraseña ingresada por el usuario. Si todo va bien, redirigiremos al usuario a userHome.html . Y si hay algún error, mostraremos error.html con el mensaje de error.

Aquí está el validateLogin completo código:

@app.route('/api/validateLogin',methods=['POST'])
def validateLogin():
    try:
        _username = request.form['inputEmail']
        _password = request.form['inputPassword']



        # connect to mysql

        con = mysql.connect()
        cursor = con.cursor()
        cursor.callproc('sp_validateLogin',(_username,))
        data = cursor.fetchall()




        if len(data) > 0:
            if check_password_hash(str(data[0][3]),_password):
                session['user'] = data[0][0]
                return redirect('/userHome')
            else:
                return render_template('error.html',error = 'Wrong Email address or Password')
        else:
            return render_template('error.html',error = 'Wrong Email address or Password')


    except Exception as e:
        return render_template('error.html',error = str(e))
    finally:
        cursor.close()
        con.close()

Cree una página llamada userhome.html dentro de la carpeta de plantillas y agregue el siguiente código HTML:

<!DOCTYPE html>
<html lang="en">
    <head>
		    
		<title>Python Flask Bucket List App - Home</title>
		    
		<link
			href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
			rel="stylesheet"
			integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
			crossorigin="anonymous"
		/>
	</head>

	<body>
		    
		<div class="container">
			        
			<div class="header">
				            
				<nav
					class="border-bottom flex-wrap mb-4 py-3 d-flex justify-content-center"
				>
					<a
						href="/"
						class="text-dark text-decoration-none mb-3 mb-md-0 d-flex align-items-center me-md-auto"
					>
						<span class="fs-4">Python Flask App</span>
					</a>

					<ul class="nav nav-pills">
						<li class="nav-item">
							<a href="/userhome" class="nav-link">Home</a>
						</li>
						<li class="nav-item">
							<a href="/logout" class="nav-link active">Logout</a>
						</li>
					</ul>
					                        
				</nav>
				        
			</div>
			<div class="bg-light rounded-3 mb-4 p-5">
				<div class="container-fluid py-5">
					<h1 class="text-center fw-bold display-5">Welcome Home!</h1>
				</div>
			</div>
			        
			<footer class="footer">
				            
				<p>&copy; Company 2022</p>
				        
			</footer>

			    
		</div>
	</body>
</html>

Además, cree una página de error llamada error.html en las templates carpeta y agregue el siguiente código HTML:

<!DOCTYPE html>
<html lang="en">
    <head>
		    
		<title>Error - Python Flask App</title>
		    
		<link
			href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
			rel="stylesheet"
			integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
			crossorigin="anonymous"
		/>
	</head>

	<body>
		    
		<div class="container">
			        
			<div class="header">
				            
				<nav
					class="border-bottom flex-wrap mb-4 py-3 d-flex justify-content-center"
				>
					<a
						href="/"
						class="text-dark text-decoration-none mb-3 mb-md-0 d-flex align-items-center me-md-auto"
					>
						<span class="fs-4">Python Flask App</span>
					</a>

					<ul class="nav nav-pills">
						<li class="nav-item">
							<a href="/" class="nav-link">Home</a>
						</li>
						<li class="nav-item">
							<a href="/signup" class="nav-link">Signup</a>
						</li>
						<li class="nav-item">
							<a href="/signin" class="nav-link">Sign In</a>
						</li>
					</ul>
					                        
				</nav>
				        
			</div>
			<div class="bg-light rounded-3 mb-4 p-5">
				<div class="container-fluid py-5">
					<h1 class="text-center fw-bold display-5">{{error}}</h1>
				</div>
			</div>
			        
			<footer class="footer">
				            
				<p>&copy; Company 2022</p>
				        
			</footer>

			    
		</div>
	</body>
</html>

Dentro de error.html , tenemos un elemento como se muestra:

<h1 class="text-center fw-bold display-5">{{error}}</h1>

El valor de la variable se puede pasar desde render_template y se puede configurar dinámicamente.

En el inicio de sesión exitoso, estamos redirigiendo al usuario a la página de inicio del usuario, por lo que debemos crear una ruta llamada /userHome como se muestra:

@app.route('/userHome')
def userHome():
    return render_template('userHome.html')
    

Guarde todos los cambios y reinicie el servidor. Haga clic en Iniciar sesión en la página de inicio e intente iniciar sesión con una dirección de correo electrónico y una contraseña válidas. En una validación de usuario exitosa, debería tener una página como la que se muestra a continuación:

En una validación de usuario fallida, el usuario será redirigido a una página de error como se muestra a continuación:

Aquí hemos usado una página de error separada para mostrar el error. También está bien si desea utilizar la misma página para mostrar el mensaje de error.

Restricción del acceso no autorizado a la página de inicio del usuario

En la validación exitosa del usuario, se redirige a un usuario a la página de inicio del usuario. Pero ahora mismo, incluso un usuario no autorizado puede ver la página de inicio simplemente navegando por la URL http://localhost:5000/userhome.

Para restringir el acceso de usuarios no autorizados, buscaremos una variable de sesión que configuraremos cuando el usuario inicie sesión correctamente. Así que importa session del matraz:

from flask import session

También necesitamos establecer una clave secreta para la sesión. Entonces en app.py , después de inicializar la aplicación, configure la clave secreta como se muestra:

app.secret_key = 'why would I tell you my secret key?'

Ahora, dentro de validateLogin antes de redirigir al usuario a /userhome en el inicio de sesión exitoso, configure la session variable como se muestra:

session['user'] = data[0][0]

A continuación, dentro de userhome método, verifique la variable de sesión antes de renderizar userhome.html . Si no se encuentra la variable de sesión, redirija a la página de error.

@app.route('/userhome')
def userHome():
    if session.get('user'):
        return render_template('userhome.html')
    else:
        return render_template('error.html',error = 'Unauthorized Access')

Guarde todos los cambios y reinicie el servidor. Sin iniciar sesión, intente navegar a http://localhost:5000/userhome y, dado que aún no ha iniciado sesión, debería ser redirigido a la página de error.

Implementación del cierre de sesión

La implementación de la función de cierre de sesión es la más sencilla. Todo lo que tenemos que hacer es hacer que la variable de sesión sea user nulo y redirigir al usuario a la página principal.

Dentro de app.py , cree una nueva ruta y método para logout como se muestra:

@app.route('/logout')
def logout():
    session.pop('user',None)
    return redirect('/')

Ya hemos configurado el href para el botón de cierre de sesión en /logout . Así que guarde todos los cambios y reinicie el servidor. Desde la página de inicio, haga clic en Iniciar sesión e intente iniciar sesión con una dirección de correo electrónico y una contraseña válidas. Una vez que haya iniciado sesión, haga clic en Cerrar sesión en la página de inicio del usuario y debería cerrar sesión correctamente en la aplicación.