Mysql
 sql >> Base de données >  >> RDS >> Mysql

Créer une application Web à partir de rien avec Python Flask et MySQL :2e partie

Dans la partie précédente de cette série, nous avons vu comment démarrer avec Python Flask et MySQL et implémenté la partie d'enregistrement des utilisateurs de notre application. Dans ce didacticiel, nous allons passer au niveau supérieur en implémentant la fonctionnalité de connexion et de déconnexion pour notre application.

Mise en route

Clonez d'abord le code source du tutoriel précédent depuis GitHub.

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

Une fois le code source cloné, accédez à la part-1 répertoire et démarrez le serveur.

python app.py

Pointez votre navigateur sur https://localhost:5000 et vous devriez avoir l'application en cours d'exécution.

Création de l'interface de connexion

Accédez à FlaskApp/templates et créez un nouveau fichier appelé signin.html . Ouvrez signin.html et ajoutez le code HTML suivant :

<!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>

Ouvrez app.py et ajoutez une nouvelle route pour l'interface de connexion.

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

Ensuite, ouvrez index.html et signup.html , et ajoutez le href lien pour la connexion sur les deux pages en tant que /signin . Enregistrez toutes les modifications et redémarrez le serveur.

python app.py

Pointez votre navigateur sur http://localhost:5000 et cliquez sur Connexion lien, et vous devriez pouvoir voir la page de connexion.

Mise en œuvre de la connexion

Maintenant, nous devons créer une fonction pour valider la connexion de l'utilisateur. En cliquant sur Connexion , nous publierons l'adresse e-mail et le mot de passe saisis dans la fonction de validation de l'utilisateur.

Création d'une procédure stockée

Pour valider un utilisateur, nous aurons besoin d'une procédure stockée MySQL. Créez donc une procédure stockée MySQL comme indiqué :

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 ;

Nous obtiendrons les détails de l'utilisateur en fonction du username depuis la base de données MySQL en utilisant sp_validateLogin . Une fois que nous aurons le mot de passe haché, nous le validerons par rapport au mot de passe saisi par l'utilisateur.

Valider la méthode utilisateur

Créez une méthode pour valider l'utilisateur que nous appellerons lorsque l'utilisateur soumettra le formulaire :

@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))

Comme on le voit dans le code ci-dessus, nous avons lu l'adresse e-mail et le mot de passe affichés dans _username et _password . Nous allons maintenant appeler le sp_validateLogin procédure avec le paramètre _username . Créez donc une connexion MySQL dans le validatelogin méthode :

con = mysql.connect()

Une fois la connexion créée, créez un cursor en utilisant le con connexion.

cursor = con.cursor()

À l'aide du curseur, appelez la procédure stockée MySQL comme indiqué :

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

Obtenez les enregistrements récupérés à partir du curseur comme indiqué :

data = cursor.fetchall()

Si les données contiennent des enregistrements, nous associerons le mot de passe récupéré au mot de passe saisi par l'utilisateur.

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.')

Comme on le voit dans le code ci-dessus, nous avons utilisé une méthode appelée check_password_hash pour vérifier si le mot de passe de hachage renvoyé correspond au mot de passe saisi par l'utilisateur. Si tout va bien, nous redirigerons l'utilisateur vers userHome.html . Et s'il y a une erreur, nous afficherons error.html avec le message d'erreur.

Voici le validateLogin complet code :

@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()

Créez une page appelée userhome.html dans le dossier des modèles et ajoutez le code HTML suivant :

<!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>

Créez également une page d'erreur appelée error.html dans les templates dossier et ajoutez le code HTML suivant :

<!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>

Dans error.html , nous avons un élément comme indiqué :

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

La valeur de la variable peut être transmise depuis le render_template fonction et peut être défini dynamiquement.

Une fois la connexion réussie, nous redirigeons l'utilisateur vers la page d'accueil de l'utilisateur, nous devons donc créer une route appelée /userHome comme indiqué :

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

Enregistrez toutes les modifications et redémarrez le serveur. Cliquez sur Connexion sur la page d'accueil et essayez de vous connecter à l'aide d'une adresse e-mail et d'un mot de passe valides. Une fois la validation de l'utilisateur réussie, vous devriez avoir une page comme illustré ci-dessous :

En cas d'échec de la validation de l'utilisateur, l'utilisateur sera redirigé vers une page d'erreur comme indiqué ci-dessous :

Ici, nous avons utilisé une page d'erreur distincte pour afficher l'erreur. C'est également très bien si vous souhaitez utiliser la même page pour afficher le message d'erreur.

Restreindre l'accès non autorisé à la page d'accueil de l'utilisateur

En cas de validation réussie de l'utilisateur, un utilisateur est redirigé vers la page d'accueil de l'utilisateur. Mais à l'heure actuelle, même un utilisateur non autorisé peut afficher la page d'accueil en parcourant simplement l'URL http://localhost:5000/userhome.

Pour restreindre l'accès des utilisateurs non autorisés, nous vérifierons une variable de session que nous définirons lors de la connexion réussie de l'utilisateur. Alors importez session du flacon :

from flask import session

Nous devons également définir une clé secrète pour la session. Donc dans app.py , une fois l'application initialisée, définissez la clé secrète comme indiqué :

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

Maintenant, à l'intérieur du validateLogin méthode, avant de rediriger l'utilisateur vers /userhome une fois la connexion réussie, définissez la session variable comme indiqué :

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

Ensuite, dans le userhome méthode, vérifiez la variable de session avant de rendre userhome.html . Si la variable de session est introuvable, redirigez vers la page d'erreur.

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

Enregistrez toutes les modifications et redémarrez le serveur. Sans vous connecter, essayez d'accéder à http://localhost:5000/userhome et puisque vous n'êtes pas encore connecté, vous devriez être redirigé vers la page d'erreur.

Mise en œuvre de la déconnexion

La mise en œuvre de la fonctionnalité de déconnexion est la plus simple. Tout ce que nous avons à faire est de rendre la variable de session user null et rediriger l'utilisateur vers la page principale.

Dans app.py , créez une nouvelle route et une nouvelle méthode pour logout comme indiqué :

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

Nous avons déjà défini le href du bouton de déconnexion sur /logout . Enregistrez donc toutes les modifications et redémarrez le serveur. Depuis la page d'accueil, cliquez sur Connexion et essayez de vous connecter avec une adresse e-mail et un mot de passe valides. Une fois connecté, cliquez sur Déconnexion dans l'accueil de l'utilisateur et vous devriez être déconnecté avec succès de l'application.