В предишната част от тази серия видяхме как да започнем с Python Flask и MySQL и внедрихме частта за регистрация на потребител от нашето приложение. В този урок ще изведем това на следващото ниво, като внедрим функцията за влизане и излизане за нашето приложение.
Първи стъпки
Първо клонирайте изходния код на предишния урок от GitHub.
git clone https://github.com/tutsplus/create-a-web-app-from-scratch-using-python-flask-and-mysql/.git
След като изходният код е клониран, отидете до част-1 директория и стартирайте сървъра.
python app.py
Насочете браузъра си към https://localhost:5000 и трябва да стартирате приложението.
Създаване на интерфейса за вход
Придвижете се до FlaskApp/templates и създайте нов файл, наречен signin.html . Отворете signin.html и добавете следния 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>
Отворете app.py и добавете нов маршрут за интерфейса за вход.
@app.route('/signin') def showSignin(): return render_template('signin.html')
След това отворете index.html и signup.html и добавете href
връзка за влизане и на двете страници като /signin
. Запазете всички промени и рестартирайте сървъра.
python app.py
Насочете браузъра си към http://localhost:5000 и щракнете върху Вход връзка и трябва да можете да видите страницата за вход.
Внедряване на влизане
Сега трябва да създадем функция за валидиране на потребителското влизане. При щракване върху Вход , ще публикуваме въведените имейл адрес и парола във функцията за валидиране на потребителя.
Създаване на съхранена процедура
За да потвърдим потребител, ще ни е необходима съхранена процедура в MySQL. Така че създайте MySQL съхранена процедура, както е показано:
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 ;
Ще получим данните за потребителя въз основа на username
от базата данни MySQL с помощта на sp_validateLogin
. След като имаме хешираната парола, ще я потвърдим спрямо въведената от потребителя парола.
Проверка на потребителския метод
Създайте метод за валидиране на потребителя, който ще извикаме, когато потребителят изпрати формуляра:
@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))
Както се вижда в горния код, ние прочетохме публикуваните имейл адрес и парола в _username
и _password
. Сега ще извикаме sp_validateLogin
процедура с параметъра _username
. Така че създайте MySQL връзка вътре в validatelogin
метод:
con = mysql.connect()
След като връзката бъде създадена, създайте cursor
с помощта на con
връзка.
cursor = con.cursor()
Използвайки курсора, извикайте съхранената процедура на MySQL, както е показано:
cursor.callproc('sp_validateLogin',(_username,))
Вземете извлечените записи от курсора, както е показано:
data = cursor.fetchall()
Ако данните имат някакви записи, ще съпоставим извлечената парола с въведената от потребителя.
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.')
Както се вижда в горния код, ние използвахме метод, наречен check_password_hash
за да проверите дали върнатата хеш парола съвпада с въведената от потребителя парола. Ако всичко е наред, тогава ще пренасочим потребителя към userHome.html . И ако има някаква грешка, ще покажем error.html със съобщението за грешка.
Ето пълния validateLogin
код:
@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()
Създайте страница, наречена userhome.html в папката с шаблони и добавете следния 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>
Също така създайте страница за грешка, наречена error.html в templates
папка и добавете следния 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>
Вътре в error.html , имаме елемент, както е показано:
<h1 class="text-center fw-bold display-5">{{error}}</h1>
Стойността за променливата може да бъде предадена от render_template
функция и може да се задава динамично.
При успешно влизане ние пренасочваме потребителя към началната страница на потребителя, така че трябва да създадем маршрут, наречен /userHome
както е показано:
@app.route('/userHome') def userHome(): return render_template('userHome.html')
Запазете всички промени и рестартирайте сървъра. Кликнете върху Вход връзка на началната страница и опитайте да влезете с валиден имейл адрес и парола. При успешно валидиране на потребителя трябва да имате страница, както е показано по-долу:
При неуспешна проверка на потребителя, потребителят ще бъде пренасочен към страница за грешка, както е показано по-долу:
Тук сме използвали отделна страница за грешка, за да покажем грешката. Също така е добре, ако искате да използвате същата страница за показване на съобщението за грешка.
Ограничаване на неоторизиран достъп до началната страница на потребителя
При успешно валидиране на потребителя, потребителят се пренасочва към началната страница на потребителя. Но точно сега дори неоторизиран потребител може да види началната страница, като просто прегледа URL адреса http://localhost:5000/userhome.
За да ограничим неоторизирания потребителски достъп, ще проверим за променлива на сесията, която ще зададем при успешно влизане на потребител. Така че импортирайте session
от колба:
from flask import session
Трябва също да зададем таен ключ за сесията. Така че в app.py
, след като приложението бъде инициализирано, задайте секретния ключ, както е показано :
app.secret_key = 'why would I tell you my secret key?'
Сега, вътре в validateLogin
метод, преди да пренасочите потребителя към /userhome
при успешно влизане задайте session
променлива, както е показано:
session['user'] = data[0][0]
След това вътре в userhome
метод, проверете за променливата на сесията, преди да изобразите userhome.html
. Ако променливата на сесията не бъде намерена, пренасочете към страницата за грешка.
@app.route('/userhome') def userHome(): if session.get('user'): return render_template('userhome.html') else: return render_template('error.html',error = 'Unauthorized Access')
Запазете всички промени и рестартирайте сървъра. Без да влизате, опитайте да отидете до http://localhost:5000/userhome и тъй като все още не сте влезли, трябва да бъдете пренасочени към страницата за грешка.
Внедряване на излизане
Внедряването на функцията за излизане е най-простото. Всичко, което трябва да направим, е да направим променливата на сесията user
null и пренасочва потребителя към главната страница.
Вътре в app.py , създайте нов маршрут и метод за logout
както е показано:
@app.route('/logout') def logout(): session.pop('user',None) return redirect('/')
Вече сме задали href за бутона за излизане на /logout
. Така че запазете всички промени и рестартирайте сървъра. От началната страница кликнете върху Вход и опитайте да влезете с валиден имейл адрес и парола. След като влезете, кликнете върху Изход бутон в началната страница на потребителя и трябва да излезете успешно от приложението.