Polish (Polski) translation by Katarzyna Kapusta (you can also view the original English article)
W poprzednim odcinku serii nauczyliśmy się, jak zacząć pracę z Python Flask i MySQL, i zaimplementowaliśmy część aplikacji odpowiedzialną za rejestrację użytkownika. W tym samouczku wejdziemy o poziom wyżej - zaprogramujemy funkcjonalności logowania i wylogowania.
Zaczynamy
Na początek sklonuj kod źródłowy z poprzedniego tutorialu z GitHub.
git clone https://github.com/jay3dec/PythonFlaskMySQLApp---Part-1.git
Po sklonowaniu kodu źródłowego przejdź do katalogu PythonFlaskMySQLApp---Part-1
i uruchom serwer.
python app.py
Wpisz w okienko przeglądarki http://localhost:5002 - aplikacja powinna się uruchomić.
Tworzymy interfejs logowania
Przejdź do PythonFlaskMySQLApp---Part-1/templates
i utwórz nowy plik o nazwie signin.html
. Otwórz signin.html
i wklej do niego następujący kod HTML:
<!DOCTYPE html> <html lang="en"> <head> <title>Python Flask Bucket List App</title> <link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet"> <link href="../static/css/signup.css" rel="stylesheet"> <script src="../static/js/jquery-1.11.2.js"></script> </head> <body> <div class="container"> <div class="header"> <nav> <ul class="nav nav-pills pull-right"> <li role="presentation" ><a href="/">Home</a></li> <li role="presentation" class="active"><a href="#">Sign In</a></li> <li role="presentation" ><a href="/showSignUp">Sign Up</a></li> </ul> </nav> <h3 class="text-muted">Python Flask App</h3> </div> <div class="jumbotron"> <h1>Bucket List App</h1> <form class="form-signin" action="/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 2015</p> </footer> </div> </body> </html>
Otwórz app.py
i dodaj nowe przekierowanie dla interfejsu rejestracji.
@app.route('/showSignin') def showSignin(): return render_template('signin.html')
Teraz otwórz index.html
oraz signup.html
i wstaw na obu stronach link href
do strony logowania z adresem /showSignin
. Zapisz wszystkie zmiany i zrestartuj serwer .
python app.py
Wejdź na http://localhost:5002 i kliknij łącze Sign In - powinna się wyświetlić strona logowania.



Implementujemy logowanie
Teraz potrzebna będzie funkcja, która pozwoli nam sprawdzić, czy użytkownik zalogował się poprawnie. Po kliknięciu w Sign In odeślemy podany adres e-mail wraz z hasłem do funkcji zatwierdzania użytkownika.
Tworzymy procedurę składowaną
Do sprawdzenia użytkownika będziemy potrzebowali procedury składowanej MySQL. Utwórz więc procedurę składowaną MySQL zgodnie z przykładem:
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 ;
Dane użytkownika sprawdzimy przy pomocy procedury sp_validateLogin
na podstawie loginu (username
) zapisanego w bazie MySQL. Zakodowane hasło z bazy porównamy z hasłem podanym przez użytkownika.
Metoda zatwierdzania użytkownika
Utwórz metodę do zatwierdzania użytkownika, która zostanie wywołana, gdy użytkownik prześle formularz:
@app.route('/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))
Jak widać w powyższym kodzie, przypisaliśmy podany adres e-mail i hasło do zmiennych _username
i _password
. Teraz wywołamy procedurę sp_validateLogin
z parametrem _username
. Utwórz zatem połączenie MySQL wewnątrz metody validateLogin
:
con = mysql.connect()
Gdy już mamy ustanowione połączenie, utwórz kursor (cursor
), korzystając z połączenia con
.
cursor = con.cursor()
Korzystając z kursora, wywołaj procedurę składowaną MySQL:
cursor.callproc('sp_validateLogin',(_username,))
Za pomocą kursora, wywołaj procedurę składowaną, jak w przykładzie:
data = cursor.fetchall()
Jeśli pod podanymi danymi istnieje jakiś zapis, porównamy hasło z bazy z tym wprowadzonym przez użytkownika.
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.')
Jak widać w powyższym kodzie, do sprawdzenia, czy podane hasło odpowiada zaszyfrowanemu hasłu z bazy, korzystamy z metody check_password_hash
. Jeśli wszystko się zgadza, przekierowujemy użytkownika na stronę userHome.html
. A jeśli wkradł się jakiś błąd, wyświetlamy error.html
z komunikatem o błędzie.
Oto pełny kod funkcji validateLogin
:
@app.route('/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()
Utwórz stronę o nazwie userHome.html
w folderze szablonów (templates) i dodaj następujący kod HTML:
<!DOCTYPE html> <html lang="en"> <head> <title>Python Flask Bucket List App</title> <link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet"> <link href="../static/css/signup.css" rel="stylesheet"> </head> <body> <div class="container"> <div class="header"> <nav> <ul class="nav nav-pills pull-right"> <li role="presentation" class="active"><a href="/logout">Logout</a> </li> </ul> </nav> <h3 class="text-muted">Python Flask App</h3> </div> <div class="jumbotron"> <h1>Welcome Home !!</h1> </div> <footer class="footer"> <p>© Company 2015</p> </footer> </div> </body> </html>
W tym samym folderze templates utwórz stronę z komunikatem o błędzie error.html
i umieść na niej następujący kod:
<!DOCTYPE html> <html lang="en"> <head> <title>Unauthorized Access:: Python Flask Bucket List App</title> <link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet"> </head> <body> <div class="container"> <div class="header"> <nav> <ul class="nav nav-pills pull-right"> <li role="presentation" class="active"><a href="#">Home</a> </li> <li role="presentation"><a href="/showSignin">Sign In</a> </li> <li role="presentation"><a href="/showSignUp">Sign Up</a> </li> </ul> </nav> <h3 class="text-muted">Python Flask App</h3> </div> <div class="jumbotron"> <h1>{{error}}</h1> </div> <footer class="footer"> <p>© Company 2015</p> </footer> </div> </body> </html>
Wewnątrz error.html
znalazł się taki element:
<h1>{{error}}</h1>
Wartość zmiennej zostanie nadana przez funkcję render_template
i przypisana dynamicznie.
Po pomyślnym zalogowaniu przekierujemy użytkownika do indywidualnej strony głównej, musimy więc utworzyć przekierowanie o nazwie /userHome
, jak w przykładzie:
@app.route('/userHome') def userHome(): return render_template('userHome.html')
Zapisz wszystkie zmiany i zrestartuj serwer. Kliknij łącze Sign In na stronie głównej i spróbuj zalogować się przy użyciu adresu e-mail i hasła. Po pomyślnym zalogowaniu powinna się wyświetlić taka strona:



W przypadku nieudanego logowania użytkownik zostanie przekierowany do strony o błędzie:



Do wyświetlenia komunikatu o błędzie użyliśmy osobnej strony. Można jednak również wyświetlić go na tej samej stronie.
Ograniczanie nieautoryzowanego dostępu do strony użytkownika
Po pomyślnym zalogowaniu użytkownik zostanie przekierowany na swoją stronę domową. Póki co jednak nawet niezarejestrowany użytkownik może ją zobaczyć, gdy tylko wpisze URL http://localhost:5002/userHome.
Aby uniemożliwić dostęp nieautoryzowanym użytkownikom, będziemy sprawdzać zmienną sesji, przypisywaną w momencie pomyślnego logowania użytkownika. Zaimportuj zatem flaskową bibliotekę session
:
from flask import session
Musimy nadać sesji tajny klucz. W app.py
, po inicjalizacji aplikacji, przypisz klucz sesji w taki sposób:
app.secret_key = 'why would I tell you my secret key?'
Teraz wewnątrz metody validateLogin
, przed przekierowaniem użytkownika do /userHome
po pomyślnym zalogowaniu, ustaw zmienną sesji session
jak pokazano:
session['user'] = data[0][0]
A teraz, wewnątrz metody userHome
, sprawdź zmienną sesji przed wyrenderowaniem userHome.html
. Jeśli zmiennej sesji brakuje, przekieruj użytkownika do strony o błędzie.
@app.route('/userHome') def userHome(): if session.get('user'): return render_template('userHome.html') else: return render_template('error.html',error = 'Unauthorized Access')
Zapisz wszystkie zmiany i uruchom ponownie serwer. Spróbuj, bez logowania, wejść na stronę http://localhost:5002/userHome. Ponieważ logowania nie było, powinieneś zobaczyć stronę o błędzie.



Implementacja wylogowania
Funkcjonalność wylogowania jest najłatwiejsza do implementacji. Wystarczy nadać zmiennej sesji user
wartość null i przekierować użytkownika na stronę główną.
Wewnątrz app.py
utwórz nowe przekierowanie i metodę wylogowania (logout
), jak w przykładzie:
@app.route('/logout') def logout(): session.pop('user',None) return redirect('/')
Ustawiliśmy już href dla przycisku 'wyloguj się' (log out) na adres /logout
. Zapisz zatem wszystkie zmiany i uruchom ponownie serwer. Będąc na stronie głównej, kliknij przycisk Sign in i spróbuj się zalogować, używając właściwego adresu e-mail i hasła. Po zalogowaniu, kliknij przycisk Logout na stronie użytkownika - powinieneś zostać pomyślnie wylogowany.
Podsumowanie
W tej części tutorialu zobaczyliśmy, jak można zaimplementować funkcjonalności logowania i wylogowywania. Nauczyliśmy się też odcinać dostęp do stron aplikacji nieuprawnionym użytkownikom. W kolejnej części tutorialu umożliwimy zalogowanemu użytkownikowi dodawanie i edycję wpisów blogowych w ramach aplikacji.
Kod źródłowy z tego tutorialu znadziesz na GitHub.
Daj nam znać, co sądzisz o tym artykule, w komentarzach poniżej!