Nella parte precedente di questa serie, abbiamo visto come iniziare con Python Flask e MySQL e implementato la parte relativa alla registrazione degli utenti della nostra applicazione. In questo tutorial, porteremo questo al livello successivo implementando la funzionalità di accesso e disconnessione per la nostra applicazione.
Per iniziare
Prima clona il codice sorgente del tutorial precedente da GitHub.
git clone https://github.com/tutsplus/create-a-web-app-from-scratch-using-python-flask-and-mysql/.git
Una volta clonato il codice sorgente, vai alla parte-1 directory e avvia il server.
python app.py
Punta il tuo browser su https://localhost:5000 e dovresti avere l'applicazione in esecuzione.
Creazione dell'interfaccia di accesso
Vai a FlaskApp/templates e crea un nuovo file chiamato signin.html . Apri signin.html e aggiungi il seguente codice 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>© Company 2022</p> </footer> </div> </body> </html>
Apri app.py e aggiungi un nuovo percorso per l'interfaccia di accesso.
@app.route('/signin') def showSignin(): return render_template('signin.html')
Quindi, apri index.html e signup.html e aggiungi il href
link per l'accesso su entrambe le pagine come /signin
. Salva tutte le modifiche e riavvia il server.
python app.py
Punta il browser su http://localhost:5000 e fai clic su Accedi link e dovresti essere in grado di vedere la pagina di accesso.
Implementazione dell'accesso
Ora, dobbiamo creare una funzione per convalidare l'accesso dell'utente. Facendo clic su Accedi , pubblicheremo l'indirizzo email e la password inseriti nella funzione di convalida utente.
Creazione di una stored procedure
Per convalidare un utente, avremo bisogno di una stored procedure MySQL. Quindi crea una stored procedure MySQL come mostrato:
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 ;
Otterremo i dettagli dell'utente in base al username
dal database MySQL utilizzando sp_validateLogin
. Una volta ottenuta la password con hash, la convalideremo rispetto alla password inserita dall'utente.
Convalida il metodo utente
Crea un metodo per convalidare l'utente che chiameremo quando l'utente invia il modulo:
@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))
Come visto nel codice sopra, abbiamo letto l'indirizzo email e la password pubblicati in _username
e _password
. Ora chiameremo sp_validateLogin
procedura con il parametro _username
. Quindi crea una connessione MySQL all'interno di validatelogin
metodo:
con = mysql.connect()
Una volta creata la connessione, crea un cursor
usando il con
connessione.
cursor = con.cursor()
Usando il cursore, chiama la stored procedure MySQL come mostrato:
cursor.callproc('sp_validateLogin',(_username,))
Ottieni i record recuperati dal cursore come mostrato:
data = cursor.fetchall()
Se i dati hanno dei record, abbineremo la password recuperata con la password inserita dall'utente.
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.')
Come visto nel codice sopra, abbiamo usato un metodo chiamato check_password_hash
per verificare se la password hash restituita corrisponde alla password immessa dall'utente. Se tutto va bene, reindirizzeremo l'utente a userHome.html . E se c'è qualche errore, visualizzeremo error.html con il messaggio di errore.
Ecco il validateLogin
completo codice:
@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()
Crea una pagina chiamata userhome.html all'interno della cartella dei modelli e aggiungi il seguente codice 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>© Company 2022</p> </footer> </div> </body> </html>
Inoltre, crea una pagina di errore chiamata error.html nei templates
cartella e aggiungi il seguente codice 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>© Company 2022</p> </footer> </div> </body> </html>
Dentro error.html , abbiamo un elemento come mostrato:
<h1 class="text-center fw-bold display-5">{{error}}</h1>
Il valore per la variabile può essere passato da render_template
funzione e può essere impostato dinamicamente.
Dopo l'accesso, stiamo reindirizzando l'utente alla home page dell'utente, quindi dobbiamo creare un percorso chiamato /userHome
come mostrato:
@app.route('/userHome') def userHome(): return render_template('userHome.html')
Salva tutte le modifiche e riavvia il server. Fai clic su Accedi link nella home page e prova ad accedere utilizzando un indirizzo email e una password validi. Dopo la convalida dell'utente, dovresti avere una pagina come mostrato di seguito:
In caso di convalida utente non riuscita, l'utente verrà reindirizzato a una pagina di errore come mostrato di seguito:
Qui abbiamo utilizzato una pagina di errore separata per visualizzare l'errore. Va bene anche se vuoi usare la stessa pagina per visualizzare il messaggio di errore.
Limitazione dell'accesso non autorizzato alla home page dell'utente
Dopo la convalida dell'utente, un utente viene reindirizzato alla home page dell'utente. Ma in questo momento anche un utente non autorizzato può visualizzare la home page semplicemente sfogliando l'URL http://localhost:5000/userhome.
Per limitare l'accesso di utenti non autorizzati, verificheremo una variabile di sessione che imposteremo in caso di accesso utente riuscito. Quindi importa session
dal pallone:
from flask import session
Abbiamo anche bisogno di impostare una chiave segreta per la sessione. Quindi in app.py
, dopo che l'app è stata inizializzata, imposta la chiave segreta come mostrato:
app.secret_key = 'why would I tell you my secret key?'
Ora, all'interno di validateLogin
metodo, prima di reindirizzare l'utente a /userhome
dopo l'accesso, imposta la session
variabile come mostrato:
session['user'] = data[0][0]
Successivamente, all'interno di userhome
metodo, controlla la variabile di sessione prima di eseguire il rendering di userhome.html
. Se la variabile di sessione non viene trovata, reindirizza alla pagina di errore.
@app.route('/userhome') def userHome(): if session.get('user'): return render_template('userhome.html') else: return render_template('error.html',error = 'Unauthorized Access')
Salva tutte le modifiche e riavvia il server. Senza effettuare l'accesso, prova a navigare su http://localhost:5000/userhome e poiché non hai ancora effettuato l'accesso, dovresti essere reindirizzato alla pagina di errore.
Implementazione del logout
L'implementazione della funzionalità di logout è la più semplice. Tutto quello che dobbiamo fare è rendere la variabile di sessione user
null e reindirizza l'utente alla pagina principale.
All'interno di app.py , crea un nuovo percorso e metodo per logout
come mostrato:
@app.route('/logout') def logout(): session.pop('user',None) return redirect('/')
Abbiamo già impostato l'href per il pulsante di disconnessione su /logout
. Quindi salva tutte le modifiche e riavvia il server. Dalla home page, fai clic su Accedi e prova ad accedere utilizzando un indirizzo email e una password validi. Dopo aver effettuato l'accesso, fai clic su Esci pulsante nella home page dell'utente e dovresti essere disconnesso dall'applicazione.