在本系列的前一部分中,我们了解了如何开始使用Python Flask和MySQL,并实现了应用程序的用户注册部分。 在本教程中,我们将通过为应用程序实现登录和注销功能将其带入一个新的水平。
入门
首先从GitHub克隆上一教程的源代码。
git clone https://github.com/jay3dec/PythonFlaskMySQLApp---Part-1.git
克隆源代码后,导航至PythonFlaskMySQLApp---Part-1
目录并启动服务器。
python app.py
将您的浏览器指向http:// localhost:5002 ,您应该正在运行该应用程序。
创建登录界面
导航至PythonFlaskMySQLApp---Part-1/templates
并创建一个名为signin.html
的新文件。 打开signin.html
并添加以下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>
打开app.py
并为登录界面添加新路径。
@app.route('/showSignin')
def showSignin():
return render_template('signin.html')
接下来,打开index.html
和signup.html
,并在两个页面/showSignin
href
登录链接添加为/showSignin
。 保存所有更改,然后重新启动服务器。
python app.py
将浏览器指向http:// localhost:5002 ,然后单击“ 登录”链接,您应该能够看到登录页面。
实施登录
现在,我们需要创建函数来验证用户登录。 单击登录后,我们会将输入的电子邮件地址和密码发布到验证用户功能。
创建一个存储过程
为了验证用户,我们需要一个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 ;
我们将使用sp_validateLogin
从MySQL数据库中基于username
获取用户详细信息。 获得哈希密码后,我们将根据用户输入的密码对其进行验证。
验证用户方法
创建一个方法来验证用户,我们将在用户提交表单时调用该方法:
@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
。 现在,我们将使用参数_username
调用sp_validateLogin
过程。 因此,在validateLogin
方法内创建一个MySQL连接:
con = mysql.connect()
创建连接后,请使用con
连接创建一个cursor
。
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('/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</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>
还要在templates
文件夹中创建一个名为error.html
的错误页面,并添加以下HTML代码:
<!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>
在error.html
内部,我们具有如下所示的元素:
<h1>{{error}}</h1>
变量的值可以从render_template
函数传递,并且可以动态设置。
成功登录后,我们会将用户重定向到用户主页,因此我们需要创建一个名为/userHome
的路由,如下所示:
@app.route('/userHome')
def userHome():
return render_template('userHome.html')
保存所有更改,然后重新启动服务器。 单击主页中的登录链接,然后尝试使用有效的电子邮件地址和密码登录。 在成功进行用户验证后,您应该拥有一个如下所示的页面:
如果用户验证失败,则会将用户重定向到错误页面,如下所示:
在这里,我们使用了单独的错误页面来显示错误。 如果要使用同一页面显示错误消息,也可以。
限制对用户主页的未经授权的访问
在成功进行用户验证后,用户将被重定向到用户主页。 但是现在,即使是未经授权的用户也可以通过简单地浏览URL http:// localhost:5002 / userHome来查看主页。
为了限制未经授权的用户访问,我们将检查会话变量,该变量将在用户成功登录后设置。 因此,从flask导入session
:
from flask import session
我们还需要为该会话设置一个秘密密钥。 因此,在app.py
,初始化应用程序后,按如下所示设置密钥:
app.secret_key = 'why would I tell you my secret key?'
现在,在validateLogin
方法内部,在成功登录/userHome
用户重定向到/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:5002 / userHome ,由于您尚未登录,因此应将您重定向到错误页面。
实施注销
实现注销功能是最简单的。 我们需要做的就是使会话变量user
null并将用户重定向到主页。
在app.py
,创建新的logout
路线和方法,如下所示:
@app.route('/logout')
def logout():
session.pop('user',None)
return redirect('/')
我们已经将/logout
按钮的href设置为/logout
。 因此,保存所有更改并重新启动服务器。 在主页上,单击“ 登录” ,然后尝试使用有效的电子邮件地址和密码登录。 登录后,单击用户主目录中的注销按钮,您应该成功从应用程序中注销。
结论
在本部分的教程中,我们了解了如何实现用户登录和注销功能。 我们还看到了如何限制对应用程序页面的未经授权的访问。 在本教程的下一部分中,我们将为登录用户实现在应用程序中添加和编辑博客文章的功能。
该教程的源代码可在GitHub上获得 。
请在下面的评论中告诉我们您的想法!