I den forrige del af denne serie så vi, hvordan man kommer i gang med Python Flask og MySQL og implementerede brugerregistreringsdelen af vores applikation. I dette selvstudie tager vi dette til næste niveau ved at implementere login- og logout-funktionaliteten til vores applikation.
Kom godt i gang
Klon først kildekoden til den forrige tutorial fra GitHub.
git clone https://github.com/tutsplus/create-a-web-app-from-scratch-using-python-flask-and-mysql/.git
Når kildekoden er blevet klonet, skal du navigere til del-1 bibliotek og start serveren.
python app.py
Peg din browser til https://localhost:5000, og du bør have programmet kørende.
Oprettelse af logingrænsefladen
Naviger til FlaskApp/skabeloner og opret en ny fil kaldet signin.html . Åbn signin.html og tilføj følgende HTML-kode:
<!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>
Åbn app.py og tilføje en ny rute til login-grænsefladen.
@app.route('/signin') def showSignin(): return render_template('signin.html')
Åbn derefter index.html og signup.html , og tilføj href
link til login på begge sider som /signin
. Gem alle ændringerne og genstart serveren.
python app.py
Peg din browser til http://localhost:5000 og klik på Log ind link, og du burde kunne se login-siden.
Implementering af log-in
Nu skal vi oprette en funktion for at validere brugerlogin. Ved at klikke på Log ind , sender vi den indtastede e-mailadresse og adgangskode til valideringsbrugerfunktionen.
Oprettelse af en lagret procedure
For at validere en bruger har vi brug for en MySQL-lagret procedure. Så opret en MySQL-lagret procedure som vist:
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 ;
Vi får brugeroplysningerne baseret på username
fra MySQL-databasen ved hjælp af sp_validateLogin
. Når vi har den hash-kodede adgangskode, validerer vi den i forhold til den adgangskode, som brugeren har indtastet.
Valider brugermetoden
Opret en metode til at validere brugeren, som vi kalder, når brugeren indsender formularen:
@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))
Som det fremgår af ovenstående kode, har vi læst den opslåede e-mailadresse og adgangskode ind i _username
og _password
. Nu kalder vi sp_validateLogin
procedure med parameteren _username
. Så opret en MySQL-forbindelse inde i validatelogin
metode:
con = mysql.connect()
Når forbindelsen er oprettet, skal du oprette en cursor
ved hjælp af con
forbindelse.
cursor = con.cursor()
Brug markøren til at kalde den MySQL-lagrede procedure som vist:
cursor.callproc('sp_validateLogin',(_username,))
Hent de hentede poster fra markøren som vist:
data = cursor.fetchall()
Hvis dataene har nogle registreringer, matcher vi den hentede adgangskode med den adgangskode, som brugeren har indtastet.
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.')
Som det ses i ovenstående kode, har vi brugt en metode kaldet check_password_hash
for at kontrollere, om den returnerede hash-adgangskode matcher den adgangskode, som brugeren har indtastet. Hvis alt er i orden, omdirigerer vi brugeren til userHome.html . Og hvis der er en fejl, viser vi error.html med fejlmeddelelsen.
Her er det komplette validateLogin
kode:
@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()
Opret en side kaldet userhome.html inde i skabelonmappen og tilføj følgende HTML-kode:
<!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>
Opret også en fejlside kaldet error.html i templates
mappe og tilføj følgende HTML-kode:
<!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>
Inde i error.html , har vi et element som vist:
<h1 class="text-center fw-bold display-5">{{error}}</h1>
Værdien for variablen kan overføres fra render_template
funktion og kan indstilles dynamisk.
Ved vellykket login omdirigerer vi brugeren til brugerens hjemmeside, så vi skal oprette en rute kaldet /userHome
som vist:
@app.route('/userHome') def userHome(): return render_template('userHome.html')
Gem alle ændringerne og genstart serveren. Klik på Log ind link på startsiden, og prøv at logge ind med en gyldig e-mailadresse og adgangskode. Ved vellykket brugervalidering bør du have en side som vist nedenfor:
Ved en mislykket brugervalidering vil brugeren blive omdirigeret til en fejlside som vist nedenfor:
Her har vi brugt en separat fejlside til at vise fejlen. Det er også fint, hvis du vil bruge den samme side til at vise fejlmeddelelsen.
Begrænsning af uautoriseret adgang til brugerhjemmesiden
Ved vellykket brugervalidering omdirigeres en bruger til brugerens hjemmeside. Men lige nu kan selv en uautoriseret bruger se startsiden ved blot at gennemse URL'en http://localhost:5000/userhome.
For at begrænse uautoriseret brugeradgang søger vi efter en sessionsvariabel, som vi indstiller ved vellykket brugerlogin. Så importer session
fra kolben:
from flask import session
Vi skal også indstille en hemmelig nøgle til sessionen. Så i app.py
, efter at appen er blevet initialiseret, skal du indstille den hemmelige nøgle som vist :
app.secret_key = 'why would I tell you my secret key?'
Nu inde i validateLogin
metode, før du omdirigerer brugeren til /userhome
ved vellykket login skal du indstille session
variabel som vist:
session['user'] = data[0][0]
Dernæst inde i userhome
metode, skal du kontrollere for sessionsvariablen, før du gengiver userhome.html
. Hvis sessionsvariablen ikke findes, skal du omdirigere til fejlsiden.
@app.route('/userhome') def userHome(): if session.get('user'): return render_template('userhome.html') else: return render_template('error.html',error = 'Unauthorized Access')
Gem alle ændringerne og genstart serveren. Uden at logge ind, prøv at navigere til http://localhost:5000/userhome, og da du ikke er logget ind endnu, bør du blive omdirigeret til fejlsiden.
Implementering af logout
Implementering af logout-funktionaliteten er den enkleste. Det eneste, vi skal gøre, er at gøre sessionsvariablen til user
null og omdiriger brugeren til hovedsiden.
Inde i app.py , opret en ny rute og metode til logout
som vist:
@app.route('/logout') def logout(): session.pop('user',None) return redirect('/')
Vi har allerede indstillet href for log ud-knappen til /logout
. Så gem alle ændringerne og genstart serveren. Fra startsiden skal du klikke på Log ind og prøv at logge ind med en gyldig e-mailadresse og adgangskode. Når du har logget ind, skal du klikke på Log ud knappen i brugerens startside, og du skulle være logget ud af applikationen.