In het vorige deel van deze serie hebben we gezien hoe we aan de slag konden met Python Flask en MySQL en hebben we het gebruikersregistratiegedeelte van onze applicatie geïmplementeerd. In deze zelfstudie brengen we dit naar een hoger niveau door de in- en uitlogfunctionaliteit voor onze applicatie te implementeren.
Aan de slag
Kloon eerst de broncode van de vorige tutorial van GitHub.
git clone https://github.com/tutsplus/create-a-web-app-from-scratch-using-python-flask-and-mysql/.git
Nadat de broncode is gekloond, navigeert u naar de part-1 directory en start de server.
python app.py
Ga met je browser naar https://localhost:5000 en je zou de applicatie moeten laten draaien.
De aanmeldingsinterface maken
Navigeer naar FlaskApp/templates en maak een nieuw bestand aan met de naam signin.html . Open signin.html en voeg de volgende HTML-code toe:
<!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>© Company 2022</p> </footer> </div> </body> </html>
Open app.py en voeg een nieuwe route toe voor de aanmeldingsinterface.
@app.route('/signin') def showSignin(): return render_template('signin.html')
Open vervolgens index.html en aanmelden.html , en voeg de href
. toe link voor inloggen op beide pagina's als /signin
. Sla alle wijzigingen op en start de server opnieuw op.
python app.py
Ga met uw browser naar http://localhost:5000 en klik op Aanmelden link, en u zou de aanmeldingspagina moeten kunnen zien.
Aanmelding implementeren
Nu moeten we een functie maken om de gebruikersaanmelding te valideren. Door te klikken op Aanmelden , zullen we het ingevoerde e-mailadres en wachtwoord posten in de functie Gebruikers valideren.
Een opgeslagen procedure maken
Om een gebruiker te valideren, hebben we een MySQL-opgeslagen procedure nodig. Maak dus een MySQL-opgeslagen procedure aan zoals weergegeven:
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 ;
We krijgen de gebruikersgegevens op basis van de username
uit de MySQL-database met behulp van sp_validateLogin
. Zodra we het gehashte wachtwoord hebben, valideren we het met het wachtwoord dat door de gebruiker is ingevoerd.
Valideer de gebruikersmethode
Maak een methode om de gebruiker te valideren die we zullen aanroepen wanneer de gebruiker het formulier indient:
@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))
Zoals te zien is in de bovenstaande code, hebben we het geposte e-mailadres en wachtwoord ingelezen in _username
en _password
. Nu noemen we de sp_validateLogin
procedure met de parameter _username
. Maak dus een MySQL-verbinding aan binnen de validatelogin
methode:
con = mysql.connect()
Nadat de verbinding is gemaakt, maakt u een cursor
met behulp van de con
verbinding.
cursor = con.cursor()
Roep met de cursor de MySQL-opgeslagen procedure op zoals weergegeven:
cursor.callproc('sp_validateLogin',(_username,))
Haal de opgehaalde records van de cursor zoals weergegeven:
data = cursor.fetchall()
Als de gegevens enkele records bevatten, vergelijken we het opgehaalde wachtwoord met het wachtwoord dat door de gebruiker is ingevoerd.
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.')
Zoals te zien is in de bovenstaande code, hebben we een methode gebruikt genaamd check_password_hash
om te controleren of het geretourneerde hash-wachtwoord overeenkomt met het wachtwoord dat door de gebruiker is ingevoerd. Als alles goed is, zullen we de gebruiker omleiden naar userHome.html . En als er een fout is, geven we error.html . weer met de foutmelding.
Hier is de volledige validateLogin
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()
Maak een pagina met de naam userhome.html in de map sjablonen en voeg de volgende HTML-code toe:
<!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>© Company 2022</p> </footer> </div> </body> </html>
Maak ook een foutpagina met de naam error.html in de templates
map en voeg de volgende HTML-code toe:
<!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>© Company 2022</p> </footer> </div> </body> </html>
Binnen error.html , we hebben een element zoals weergegeven:
<h1 class="text-center fw-bold display-5">{{error}}</h1>
De waarde voor de variabele kan worden doorgegeven vanuit de render_template
functie en kan dynamisch worden ingesteld.
Na een succesvolle aanmelding leiden we de gebruiker om naar de startpagina van de gebruiker, dus we moeten een route maken met de naam /userHome
zoals getoond:
@app.route('/userHome') def userHome(): return render_template('userHome.html')
Sla alle wijzigingen op en start de server opnieuw op. Klik op de Aanmelden link op de startpagina en probeer u aan te melden met een geldig e-mailadres en wachtwoord. Na succesvolle gebruikersvalidatie zou u een pagina moeten hebben zoals hieronder weergegeven:
Bij een mislukte gebruikersvalidatie wordt de gebruiker omgeleid naar een foutpagina zoals hieronder weergegeven:
Hier hebben we een aparte foutpagina gebruikt om de fout weer te geven. Het is ook prima als je dezelfde pagina wilt gebruiken om de foutmelding weer te geven.
Ongeautoriseerde toegang tot de startpagina van de gebruiker beperken
Na succesvolle gebruikersvalidatie wordt een gebruiker doorgestuurd naar de startpagina van de gebruiker. Maar op dit moment kan zelfs een niet-geautoriseerde gebruiker de startpagina bekijken door simpelweg te bladeren door de URL http://localhost:5000/userhome.
Om ongeautoriseerde gebruikerstoegang te beperken, controleren we op een sessievariabele die we instellen op succesvolle gebruikersaanmelding. Dus importeer session
uit kolf:
from flask import session
We moeten ook een geheime sleutel voor de sessie instellen. Dus in app.py
, nadat de app is geïnitialiseerd, stelt u de geheime sleutel in zoals weergegeven:
app.secret_key = 'why would I tell you my secret key?'
Nu, binnen de validateLogin
methode, voordat de gebruiker wordt omgeleid naar /userhome
stel bij succesvolle aanmelding de session
in variabele zoals weergegeven:
session['user'] = data[0][0]
Vervolgens, in de userhome
methode, controleer dan op de sessievariabele voordat u userhome.html
weergeeft . Als de sessievariabele niet wordt gevonden, wordt u doorgestuurd naar de foutpagina.
@app.route('/userhome') def userHome(): if session.get('user'): return render_template('userhome.html') else: return render_template('error.html',error = 'Unauthorized Access')
Sla alle wijzigingen op en start de server opnieuw op. Probeer zonder in te loggen naar http://localhost:5000/userhome te gaan en aangezien u nog niet bent ingelogd, zou u moeten worden doorgestuurd naar de foutpagina.
Uitloggen implementeren
Het implementeren van de uitlogfunctionaliteit is het eenvoudigst. Het enige wat we moeten doen is de sessievariabele user
. maken null en stuur de gebruiker door naar de hoofdpagina.
Binnen app.py , maak een nieuwe route en methode voor logout
zoals getoond:
@app.route('/logout') def logout(): session.pop('user',None) return redirect('/')
We hebben de href voor de uitlogknop al ingesteld op /logout
. Sla dus alle wijzigingen op en start de server opnieuw op. Klik op de startpagina op Aanmelden en probeer in te loggen met een geldig e-mailadres en wachtwoord. Nadat u zich heeft aangemeld, klikt u op Uitloggen knop in de startpagina van de gebruiker en u zou met succes moeten zijn uitgelogd bij de applicatie.