В предыдущей части этой серии статей мы увидели, как начать работу с Python Flask и MySQL, и реализовали часть приложения для регистрации пользователей. В этом руководстве мы переходим на следующий уровень, реализуя функции входа и выхода для нашего приложения.
Начиная
Сначала клонируйте исходный код предыдущего урока из GitHub .
1
|
git clone https://github.com/jay3dec/PythonFlaskMySQLApp—Part-1.git
|
После того, как исходный код был клонирован, перейдите в PythonFlaskMySQLApp---Part-1
и запустите сервер.
1
|
python app.py
|
Укажите в браузере http: // localhost: 5002, и приложение должно быть запущено.
Создание интерфейса входа
Перейдите к PythonFlaskMySQLApp---Part-1/templates
и создайте новый файл с именем signin.html
. Откройте signin.html
и добавьте следующий HTML-код:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
<!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>©
</footer>
</div>
</body>
</html>
|
Откройте app.py
и добавьте новый маршрут для интерфейса входа.
1
2
3
|
@app.route(‘/showSignin’)
def showSignin():
return render_template(‘signin.html’)
|
Затем откройте index.html
и signup.html
и добавьте ссылку href
для входа на обе страницы как /showSignin
. Сохраните все изменения и перезапустите сервер.
1
|
python app.py
|
В браузере укажите http: // localhost: 5002 и нажмите на ссылку « Войти» , и вы увидите страницу входа.
Реализация входа
Теперь нам нужно создать функцию для проверки логина пользователя. При нажатии на кнопку « Войти» мы отправим введенный адрес электронной почты и пароль в функцию подтверждения пользователя.
Создание хранимой процедуры
Для проверки пользователя нам понадобится хранимая процедура MySQL. Поэтому создайте хранимую процедуру MySQL, как показано ниже:
1
2
3
4
5
6
7
8
|
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
. Получив хешированный пароль, мы проверим его по паролю, введенному пользователем.
Подтвердите метод пользователя
Создайте метод для проверки пользователя, который мы будем вызывать, когда пользователь отправляет форму:
1
2
3
4
5
6
7
8
|
@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))
|
Как видно из приведенного выше кода, мы прочитали адрес электронной почты и пароль в _username
и _password
. Теперь мы sp_validateLogin
процедуру sp_validateLogin
с параметром _username
. Поэтому создайте соединение MySQL внутри метода validateLogin
:
1
|
con = mysql.connect()
|
Как только соединение будет создано, создайте cursor
используя соединение con
.
1
|
cursor = con.cursor()
|
Используя курсор, вызовите хранимую процедуру MySQL, как показано ниже:
1
|
cursor.callproc(‘sp_validateLogin’,(_username,))
|
Получить извлеченные записи из курсора, как показано:
1
|
data = cursor.fetchall()
|
Если данные содержат несколько записей, мы сопоставим полученный пароль с паролем, введенным пользователем.
1
2
3
4
5
6
7
|
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
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
@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()
|
Создайте страницу с именем userHome.html
внутри папки шаблонов и добавьте следующий HTML-код:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
<!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>©
</footer>
</div>
</body>
</html>
|
Также создайте страницу ошибки с именем error.html
в папке templates
и добавьте следующий HTML-код:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
<!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>©
</footer>
</div>
</body>
</html>
|
Внутри error.html
у нас есть элемент, как показано:
1
|
<h1>{{error}}</h1>
|
Значение для переменной может быть передано из функции render_template
и может быть установлено динамически.
При успешном входе мы перенаправляем пользователя на домашнюю страницу пользователя, поэтому нам нужно создать маршрут с именем /userHome
как показано ниже:
1
2
3
|
@app.route(‘/userHome’)
def userHome():
return render_template(‘userHome.html’)
|
Сохраните все изменения и перезапустите сервер. Нажмите на ссылку « Войти» на главной странице и попробуйте войти, используя действующий адрес электронной почты и пароль. При успешной проверке пользователя у вас должна быть страница, как показано ниже:
При неудачной проверке пользователя пользователь будет перенаправлен на страницу ошибки, как показано ниже:
Здесь мы использовали отдельную страницу ошибок для отображения ошибки. Также хорошо, если вы хотите использовать ту же страницу для отображения сообщения об ошибке.
Ограничение несанкционированного доступа к домашней странице пользователя
При успешной проверке пользователя пользователь перенаправляется на домашнюю страницу пользователя. Но прямо сейчас даже неавторизованный пользователь может просматривать домашнюю страницу, просто просматривая URL-адрес http: // localhost: 5002 / userHome .
Чтобы ограничить неавторизованный доступ пользователей, мы проверим переменную сеанса, которую мы установим при успешном входе пользователя. Итак, импортируем session
из колбы:
1
|
from flask import session
|
Нам также нужно установить секретный ключ для сессии. Поэтому в app.py
после инициализации приложения установите секретный ключ, как показано ниже:
1
|
app.secret_key = ‘why would I tell you my secret key?’
|
Теперь внутри метода validateLogin
перед перенаправлением пользователя в /userHome
при успешном входе установите переменную session
как показано ниже:
1
|
session[‘user’] = data[0][0]
|
Затем, внутри метода userHome
, проверьте переменную сеанса перед рендерингом userHome.html
. Если переменная сеанса не найдена, перенаправьте на страницу ошибки.
1
2
3
4
5
6
|
@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: 5002 / userHome, и, поскольку вы еще не вошли в систему, вы должны будете перенаправлены на страницу с ошибкой.
Реализация выхода
Реализация функции выхода из системы является самой простой. Все, что нам нужно сделать, это сделать переменную сеанса user
нулевой и перенаправить пользователя на главную страницу.
Внутри app.py
создайте новый маршрут и метод для logout
как показано:
1
2
3
4
|
@app.route(‘/logout’)
def logout():
session.pop(‘user’,None)
return redirect(‘/’)
|
Мы уже установили href для кнопки /logout
. Сохраните все изменения и перезапустите сервер. На домашней странице нажмите « Войти» и попробуйте войти, используя действующий адрес электронной почты и пароль. После входа нажмите кнопку « Выйти» в домашней странице пользователя, и вы должны успешно выйти из приложения.
Вывод
В этой части руководства мы увидели, как реализовать функцию входа и выхода пользователя из системы. Мы также увидели, как ограничить несанкционированный доступ к страницам приложения. В следующей части этого руководства мы реализуем функциональность для вошедшего в систему пользователя, чтобы добавлять и редактировать сообщения в блоге в приложении.
Исходный код из этого урока доступен на GitHub .
Дайте нам знать ваши мысли в комментариях ниже!