如何使用Flask-Login进行用户认证——CodesCode
了解Flask-Login提供的功能,以及如何利用它们为您的Python网页应用程序创建安全的用户登录功能
在本文中,我们将介绍Flask-Login提供的各种功能,以及如何使用它们为您的Web应用程序创建安全的用户登录功能。通过阅读完本文,您将对如何在Flask应用程序中使用Flask-Login实现安全用户身份验证有很好的理解。
身份验证是任何允许用户访问数据或资源的Web应用程序的重要组成部分,因为它确保只有合适的人才能访问敏感信息。在Flask中,也可以使用Flask-Login来实现身份验证。
Flask-Login是Flask中的一个扩展,其中的函数用于处理用户的登录和注销,并在整个应用程序中跟踪当前用户。这使得在Flask应用程序中实现身份验证和授权变得非常容易。
- 为什么使用Flask-Login?
- 先决条件
- 入门
- 创建用户模型
- 创建数据库
- 密码哈希
- 创建注册视图
- 创建登录视图
- 使用受保护的视图创建注销逻辑
- 添加模板
- Flask-Login如何使用用户会话Cookie管理用户会话
- 结论
为什么使用Flask-Login?
Flask-Login具有多种功能和功能,使得在Flask应用程序中轻松执行身份验证变得容易。以下是使用Flask-Login的一些好处:
-
用户会话管理。Flask-Login处理用户会话的创建和销毁。它还可以在会话中存储当前用户的ID,以便您可以轻松检查用户是否已登录。
-
登录和注销功能。Flask-Login提供内置的登录和注销功能。这些功能负责处理所有重要的流程,如创建和销毁会话,并将用户重定向到适当的页面。
-
用户加载器回调。Flask-Login允许您定义一个用户加载器回调。此回调用于为当前会话加载用户对象。如果您使用数据库存储用户信息,则此功能非常有用。
-
身份验证和授权。Flask-Login使在应用程序中实现身份验证和授权变得容易。您可以使用Flask-Login来保护特定页面或路由,并授予用户对应用程序的不同访问级别。
先决条件
要按照本文进行操作,您需要以下内容:
- 了解Python和Flask语法
- 基本了解HTML和CSS
- 安装Python 3和Flask
显然,您还需要访问Web浏览器。
入门
要充分利用Flask登录模块,我们需要安装Flask-Login和其他必要的依赖项。这些库提供了改进应用程序功能所需的必要函数和工具。要安装它们,请打开命令提示符或终端,并执行以下pip命令:
pip install flask-login flask_sqlalchemy flask_bcrypt
下面是这些库的功能说明:
- Flask-SQLAlchemy:在Flask中与SQLAlchemy集成以进行数据库操作
- Flask-Bcrypt:为Flask中的密码安全添加Bcrypt哈希
安装完成后,Flask login将自动下载到您使用的目录中。
注意:在撰写本文时,最新版本的Flask和Werkzeug在解决依赖关系方面存在一些问题。为了解决这个问题,您必须强制安装Werkzeug的2.3.0版本,因为它是目前为止唯一可用的已知版本。
安装完成依赖项后,您需要使用Flask应用程序对其进行初始化:
from flask_sqlalchemy import SQLAlchemyfrom flask_login import UserMixin, LoginManager, login_user, logout_user, login_requiredfrom flask_bcrypt import Bcryptfrom flask_login import LoginManager app = Flask(__name__)login_manager = LoginManager()login_manager.init_app(app)
在上面的代码片段中,我们还在应用程序中初始化了LoginManager
对象。 LoginManager
是Flask-Login的扩展,用于设置处理用户会话所需的必要配置。
创建用户模型
模型是您想在应用程序中使用的数据结构的表示。它定义了数据在系统内的组织方式、存储方式和操作方式。模型通常与预先定义的结构遵循的数据库一起使用。对于我们的应用程序,我们有以下数据:
- 唯一的ID
- 用户名
- 密码(已哈希)
class User(UserMixin):id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(64), unique=True)password_hash = db.Column(db.String(128))def __repr__(self): return f'<User {self.username}>'
您还可以根据项目的范围为用户模型添加其他属性,例如电子邮件地址或个人资料图片。
创建数据库
一旦定义了用户模型,您需要创建一个数据库,用于存储我们在前一个模型中创建的数据结构。
在本文中,我们将使用SQLite数据库。这是因为SQLite是一个轻量级的无服务器数据库引擎。这使得它易于设置和使用,因为它不需要单独的安装。对于中小型应用程序而言,它也是一个很好的选择。
以下是在我们的应用程序中使用SQLite数据库的步骤:
-
要使用SQLite数据库,您必须在Flask应用程序配置中设置一个URI。这通常在顶部与其他配置一起完成。以下是您可以使用的片段:
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db' # 使用SQLite作为数据库
在这个片段中,
///...
表示到您的文件(site.db
)的相对路径,这是我们用于SQLite数据库文件的名称。此名称可以更改为任何您喜欢的名称。 -
接下来,您必须使用以下代码初始化Flask-SQLAlchemy ORM:
db = SQLAlchemy(app)
SQLAlchemy是一个对象关系映射器,提供一组工具,用于使用Python与数据库进行交互。
db = SQLAlchemy(app)
这一行创建了SQLAlchemy类的一个实例,并将其绑定到您的Flask应用程序(app
)。 -
要创建此数据库,我们必须初始化数据库,使用
create_all
方法:if __name__ == '__main__':db.create_all()app.run(debug=True)
此代码通常放置在您的Python脚本的末尾,或者放置在专用于初始化数据库的单独脚本中。一旦运行脚本,数据库文件将根据我们之前定义的模型创建相应的表。
在本例中,如果
User
表不存在,代码将创建一个名为site.db
的文件。通常,site.db
文件位于名为/instance/
的文件夹中。
接下来,我们需要创建一个user_loader
,它接受用户ID并返回相应的User
对象。以下是一个例子:
@login_manager.user_loaderdef load_user(user_id): return User.query.get(user_id)
密码哈希
密码哈希是一种安全措施,它将用户的密码的加密表示存储在数据库中。这样,即使在应用程序的安全性受到损害的情况下,获取实际密码变得更加困难。
通常,在注册过程中首先对密码进行哈希处理并存储在数据库中。然后,每当用户登录时,都会再次对其密码进行哈希处理并与存储在数据库中的哈希密码进行比较。如果两个密码匹配,用户将被认证并获得访问应用程序的权限。
如何使用Flask-Bcrypt进行密码加密和验证
Flask有一个名为Flask-Bcrypt的扩展可以帮助实现这个功能。它有两个主要函数:generate_password_hash()
和check_password_hash()
。
generate_password_hash()
函数接受用户的密码作为参数,并返回加密后的密码。通常在注册逻辑中使用。
check_password_hash()
函数接受密码和加密后的密码作为参数,并返回true
如果两个密码匹配,或者返回false
如果不匹配。这在授予登录视图之前调用。
创建注册视图
视图是Flask框架用来生成HTML、JSON或其他数据发送至用户浏览器的一部分。在这段代码中,我们将创建一个视图来接受用户的输入并将详细信息添加到数据库中:
@app.route('/register', methods=['GET', 'POST'])def register():if request.method == 'POST': username = request.form['username'] password = request.form['password'] hashed_password = bcrypt.generate_password_hash(password).decode('utf-8') new_user = User(username=username,password=hashed_password) db.session.add(new_user) db.session.commit() return redirect(url_for('welcome ')) return render_template('registeration.html')
下面是代码的详细说明:
-
首行使用了装饰器定义了URL路径为
/register
的路由。该路由接受GET和POST请求。当有请求时,与该路由相关联的register()
函数将被执行。 -
接下来,我们确认请求方法是否为POST方法:
if request.method == 'POST':
确认之后,函数获取用户在注册表单中填写的值:
username = request.form['username']password = request.form['password']
-
然后,函数查询数据库是否存在提供的用户名的用户。如果查询到用户并且密码匹配,将执行该代码块内的内容。
创建登录视图
在登录视图中,我们创建了一个逻辑,接受来自页面的输入,然后检查该输入是否与数据库中的任何行匹配:
@app.route('/login', methods=['GET', 'POST'])def login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] user = User.query.filter_by(username=username).first() if user and bcrypt.check_password_hash(user.password, password): login_user(user) return redirect(url_for('welcome')) return render_template('login.html')
下面是代码如何工作的详细说明:
-
首行使用了装饰器定义了URL路径为
/login
的路由。该路由接受GET和POST请求。当有请求时,与该路由相关联的login()
函数将被执行。 -
login()
函数首先检查请求方法是否为POST:if request.method == 'POST':
确认之后,函数获取用户在登录表单中填写的值:
username = request.form['username']password = request.form['password']
-
然后,函数查询数据库是否存在提供的用户名:
user = User.query.filter_by(username=username).first()if user and bcrypt.check_password_hash(user.password, password):
-
如果用户名和密码都通过验证,使用Flask-Login的
login_user
和redirect
函数授予用户访问权限:login_user(user)redirect(url_for('welcome'))
-
然而,如果请求方法不是POST或者提供的详细信息不正确,它将渲染
login.html
模板:return render_template('login.html')
换句话说,它检查输入的凭据是否有效,登录用户并在成功时重定向到欢迎页面。如果登录不成功或者是GET请求,它会为用户渲染登录模板,以便输入他们的凭据。
使用受保护视图创建注销逻辑
在大多数应用程序中,如果用户未登录,则无法访问某些页面。这包括交易历史、草稿和注销页面等页面。Flask-Login提供了一种方便的方式来保护这些页面/路由,并限制只有经过身份验证的用户才能访问,使用login_required
装饰器。下面是它的工作原理的详细说明。
要使用此功能,您必须从Flask-Login导入login_required
装饰器:
from flask_login import login_required
接下来,您必须将login_required
装饰器添加到要保护的任何路由中。例如,让我们创建一个只有在用户登录时才能访问的注销页面:
@app.route('/logout') @login_required def logout(): logout_user() return redirect(url_for('login'))
下面是它的工作原理的详细说明:
-
与登录视图中类似,
@app.route('/logout')
定义了URL路径/logout
的路由。 -
接下来,我们添加了一个
login_required
装饰器,确保用户必须登录才能访问logout
路由。如果用户未登录并尝试访问此路由,它们将被重定向到登录页面。 -
在
logout
函数内部,调用了logout_user()
。此函数由Flask-Login提供,用于注销当前用户。 -
注销用户后,函数使用
redirect(url_for('login'))
将其重定向到login
路由。
所以,当用户访问/logout
路由时,Flask-Login确保他们已登录(@login_required
),登出并重定向到登录页面。这有助于在您的Flask应用程序中安全地处理用户注销。login_required
装饰器应用于/protected
路由,表示仅授权的用户可以访问。如果用户尝试访问受保护的页面而未登录,则Flask-Login会将其重定向到登录页面。
添加模板
Flask中的模板允许您利用HTML页面定义站点的外观。为了完全实现我们app.py
文件中的逻辑,我们将创建下面图片所示的HTML页面。
下面的动画展示了模板如何渲染我们网站的不同页面。
https://player.vimeo.com/video/884411943
您可以在这篇文章的GitHub存储库中查看本教程的完整代码,并了解更多关于它的实现细节。
Flask-Login如何使用用户会话Cookie管理用户会话
用户会话是一种在用户登录时用于跟踪和更新用户信息的系统。Flask-Login通过在用户浏览器上存储会话Cookie来管理这些会话。会话Cookie是一个包含用户会话唯一标识符的小数据片段。
当用户使用Flask-Login登录到网站时,服务器会生成一个会话Cookie并将其发送到用户的浏览器。浏览器存储会话Cookie并在所有对服务器的请求中包含它。服务器使用会话Cookie来识别用户及其会话状态。
例如,如果用户已登录并访问由Flask-Login保护的页面,Flask-Login将检查会话Cookie以查看用户是否已通过身份验证。如果用户已通过身份验证,Flask-Login将从数据库加载用户的个人资料信息,并使其在视图中可用。如果用户未通过身份验证,Flask-Login将重定向用户到登录页面。
当用户从网站退出登录时,服务器会从用户的浏览器中删除会话 cookie,从而终止用户会话。
结论
Flask 提供了多种函数来解决认证的不同方面,包括用户会话管理和授权。通过利用这些函数,您可以为您的应用程序实施一个强大而安全的认证系统,以满足特定需求。
Leave a Reply