flask中的flask-login

在这里插入图片描述

flask中的flask-login

在 Flask 中,用户认证通常是通过使用扩展库(例如 Flask-Login、Flask-HTTPAuth 或 Flask-Security)来实现的。

本文详细地解释下 Flask 中的用户认证。这里是用 Flask-Login 插件为例,这是一个处理用户会话的插件。首先,你需要安装 Flask-Login。你可以使用 pip 来安装:

pip install flask-login

接下来,在你的应用中初始化 Flask-Login:

from flask_login import LoginManagerlogin_manager = LoginManager()

然后,在创建 Flask 应用实例之后,你需要初始化 LoginManager:

app = Flask(__name__)
login_manager.init_app(app)

Flask-Login 要求你实现一个 callback 函数,这个函数接受一个用户 ID,并返回相应的用户对象。这可以通过 user_loader 装饰器来实现:

from your_model_file import User@login_manager.user_loader
def load_user(user_id):return User.query.get(int(user_id))

这里,User 是用户模型,它应该是一个数据库模型,用来存储用户信息。在 Flask 中,常常使用 SQLAlchemy 来管理数据库。一个简单的 User 模型可能如下所示:

from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash
from flask_sqlalchemy import SQLAlchemydb = SQLAlchemy()class User(UserMixin, db.Model):id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(64), unique=True)password_hash = db.Column(db.String(128))def set_password(self, password):self.password_hash = generate_password_hash(password)def check_password(self, password):return check_password_hash(self.password_hash, password)

此处,我们还使用了 Werkzeug 提供的密码散列方法,为了保护用户的密码。

接下来,你需要创建一个登录页面。登录页面需要验证用户输入的用户名和密码:

from flask import render_template, redirect, url_for, flash
from flask_login import login_user
from your_form_file import LoginForm@app.route('/login', methods=['GET', 'POST'])
def login():form = LoginForm()if form.validate_on_submit():user = User.query.filter_by(username=form.username.data).first()if user is None or not user.check_password(form.password.data):flash('Invalid username or password')return redirect(url_for('login'))login_user(user)return redirect(url_for('index'))return render_template('login.html', form=form)

这里的 LoginForm 是一个 Flask-WTF 表单类,用来处理表单数据。

最后,你需要为用户登出设置路由:

from flask_login import logout_user@app.route('/logout')
def logout():logout_user()return redirect(url_for('index'))

在理解 Flask-Login 的执行流程之前,我们先需要理解几个关键的 Flask-Login 组件:

  1. LoginManager:它是 Flask-Login 的核心,负责管理用户会话。
  2. UserMixin:它为用户类提供默认的实现,如 is_authenticatedis_activeis_anonymousget_id
  3. user_loader:这是一个回调函数,当 Flask-Login 需要知道特定用户的信息时,会调用这个函数。这个函数应该接收一个用户 ID 作为输入,返回相应的用户对象。
  4. login_user:当用户在登录表单中提供了有效的凭证时,应用会调用这个函数,它会在用户会话中记录下该用户已登录。
  5. logout_user:当用户想要退出时,应用会调用这个函数,它会从用户会话中删除登录信息。

现在,我们来看一下 Flask-Login 的工作流程:

  1. 用户访问网站,发送一个请求到服务器。
  2. Flask 应用接收到请求,检查这个请求的会话中是否有用户 ID,如果有,那么 Flask-Login 会用这个 ID 调用 user_loader 回调函数,试图加载这个用户。
  3. 如果 user_loader 回调函数找到了用户,那么这个请求就是已认证的。如果没有找到用户,那么这个请求就是匿名的。
  4. 对于需要用户登录才能访问的视图函数,Flask-Login 会检查用户是否已认证。如果用户已认证,那么就允许访问。如果用户未认证,那么就重定向到登录页面。
  5. 在登录页面,用户会提供登录凭证,比如用户名和密码。服务器验证凭证,如果凭证有效,那么就调用 login_user 函数,记录用户已登录。
  6. 用户在浏览网站时,所有的请求都会带有用户的会话信息,所以服务器能知道是哪个用户发送的请求。
  7. 当用户决定退出时,应用会调用 logout_user 函数,删除用户的会话信息。

这就是 Flask-Login 的基本工作流程。它管理用户的登录状态,并提供一种简便的方式让你能在视图函数中访问当前用户。

补充1

Flask-Login 中的 user_loader 是一个回调函数,其执行时机主要在处理用户的请求时。每当用户发送一个请求到 Flask 应用时,Flask-Login 都会通过在用户会话(session)中存储的用户 ID 来执行 user_loader 函数,以获取对应的用户对象。

具体步骤如下:

  1. 当一个请求到达 Flask 应用时,Flask-Login 会先查看用户的会话中是否有用户 ID 存在。
  2. 如果用户会话中存在 ID,Flask-Login 就会调用 user_loader 函数,并把这个 ID 作为参数传入。
  3. user_loader 函数接收到这个 ID,然后查询数据库(或者其他存储用户数据的地方)找到对应的用户对象,并返回。
  4. Flask-Login 接着将这个用户对象存储在当前请求的上下文中,这样在处理这个请求的后续步骤中,你就可以使用 current_user 变量来访问这个用户对象了。

总的来说,user_loader 的调用是在每个请求开始时进行的,目的是为了从用户的会话中恢复用户对象,这样在处理请求时就可以知道是谁发起的请求,他/她是否有权限访问特定资源等等。

补充2

假设你有一个名为 dashboard 的视图函数,它只允许已认证的用户访问。你可以使用 Flask-Login 提供的 login_required 装饰器来实现这一点:

from flask_login import login_required@app.route('/dashboard')
@login_required
def dashboard():return render_template('dashboard.html')

如果一个已认证的用户尝试访问这个视图,他们将会正常地看到 dashboard 页面。然而,如果一个未认证的用户(例如,未登录或者会话已过期的用户)尝试访问这个视图,login_required 装饰器将会拦截这个请求,并重定向到登录页面。

你需要在 LoginManager 实例中设置登录视图的名称,以便 Flask-Login 知道未认证的用户应该被重定向到哪里:

login_manager.login_view = 'login'

这里 'login' 是登录视图函数的端点名。例如,如果你的登录视图函数像下面这样定义:

@app.route('/login', methods=['GET', 'POST'])
def login():# authentication code herepass

那么登录视图的端点名就是 ‘login’,所以上面的 login_manager.login_view = 'login' 表示未认证的用户将会被重定向到这个视图。

注意,你的登录视图函数应该处理两种请求方法:‘GET’ 和 ‘POST’。‘GET’ 请求用于显示登录表单,‘POST’ 请求用于提交表单。

补充3

这里我将为你展示一个简单的 Flask 登录页面的例子,这个例子使用了 Flask-Login 和 Flask-WTF(用于处理表单)。

首先,我们需要创建一个用于处理登录的表单类,如下:

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequiredclass LoginForm(FlaskForm):username = StringField('Username', validators=[DataRequired()])password = PasswordField('Password', validators=[DataRequired()])submit = SubmitField('Sign In')

然后,我们需要创建一个处理登录的视图函数,代码如下:

from flask import render_template, redirect, url_for, flash
from flask_login import login_user
from .forms import LoginForm
from .models import User@app.route('/login', methods=['GET', 'POST'])
def login():form = LoginForm()if form.validate_on_submit():user = User.query.filter_by(username=form.username.data).first()if user is not None and user.check_password(form.password.data):login_user(user)return redirect(url_for('dashboard'))  #

补充4:用户注册

用户注册通常涉及到以下几个步骤:创建一个用户注册表单,创建一个处理用户提交注册信息的视图函数,以及创建一个用于显示注册表单的模板。

首先,我们需要创建一个用户注册表单,如下:

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, EqualToclass RegistrationForm(FlaskForm):username = StringField('Username', validators=[DataRequired()])password = PasswordField('Password', validators=[DataRequired()])confirm_password = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password')])submit = SubmitField('Register')

然后,我们需要创建一个处理用户注册的视图函数,代码如下:

from flask import render_template, redirect, url_for, flash
from .forms import RegistrationForm
from .models import User, db@app.route('/register', methods=['GET', 'POST'])
def register():form = RegistrationForm()if form.validate_on_submit():user = User(username=form.username.data)user.set_password(form.password.data)db.session.add(user)db.session.commit()flash('Congratulations, you are now a registered user!')return redirect(url_for('login'))  # 登录页面的路由return render_template('register.html', form=form)

在这个视图函数中,当表单通过验证并提交时(form.validate_on_submit()),我们创建一个新的用户对象,并设置其密码(user.set_password(form.password.data))。然后,我们把新用户添加到数据库会话中,并提交会话以将数据写入数据库(db.session.add(user)db.session.commit())。最后,我们显示一个注册成功的消息,并重定向到登录页面。

最后,你需要在你的 ‘register.html’ 模板中添加一个显示注册表单的部分,代码可能如下:

<form method="POST">{{ form.hidden_tag() }}<p>{{ form.username.label }}<br>{{ form.username(size=20) }}</p><p>{{ form.password.label }}<br>{{ form.password(size=20) }}</p><p>{{ form.confirm_password.label }}<br>{{ form.confirm_password(size=20) }}</p><p>{{ form.submit() }}</p>
</form>

当用户在注册表单中输入用户名和密码并点击提交时,他们提供的数据将被发送到服务器进行处理。如果所有输入都满足验证规则(例如,两次输入的密码一致),一个新的用户就会被创建,并存储到数据库中。然后用户就会被重定向到登录页面。如果有任何验证失败,用户将被提示重新输入。

补充5:密码找回

密码找回功能的实现通常包括以下步骤:发送包含密码重置链接的电子邮件到用户的注册邮箱,用户点击链接后,被重定向到一个可以设置新密码的页面。

以下是一个简化的实现示例:

  1. 创建一个用于生成和验证密码重置令牌的用户模型方法

首先,在你的用户模型中,添加一个生成令牌的方法和一个验证令牌的方法。通常,可以使用 itsdangerous 库来生成签名的令牌。

from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from flask import current_appclass User(db.Model, UserMixin):# ...def get_reset_token(self, expires_sec=1800):s = Serializer(current_app.config['SECRET_KEY'], expires_sec)return s.dumps({'user_id': self.id}).decode('utf-8')@staticmethoddef verify_reset_token(token):s = Serializer(current_app.config['SECRET_KEY'])try:user_id = s.loads(token)['user_id']except:return Nonereturn User.query.get(user_id)
  1. 创建一个发送密码重置电子邮件的函数

接下来,你需要创建一个函数,该函数生成一个密码重置令牌,然后发送一封包含密码重置链接的电子邮件到用户的注册邮箱。这个链接应该包含令牌作为查询参数。

你可能会使用 Flask-Mail 插件来发送邮件。

  1. 创建密码重置请求的视图函数

创建一个视图函数来处理密码重置请求,获取用户输入的电子邮件地址,查找关联的用户,如果找到了用户,就调用上面的函数来发送密码重置电子邮件。

  1. 创建处理密码重置链接的视图函数

创建一个视图函数来处理用户点击密码重置链接后的请求。这个视图函数应该从链接的查询参数中获取令牌,然后调用用户模型的 verify_reset_token 方法来验证令牌。如果验证通过,将用户重定向到一个可以输入新密码的表单页面。

  1. 创建设置新密码的视图函数

最后,你需要创建一个视图函数来处理用户提交新密码的请求。这个视图函数应该获取用户的新密码,然后更新用户模型中的密码字段,最后把更新后的用户数据存回数据库。

这个流程需要用户能够接收和发送电子邮件,并且你的应用能够发送电子邮件。这个流程在某些方面可能需要调整以适应你的具体需求,例如邮件服务的选择,以及如何处理邮件发送失败的情况。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/77035.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

21.Netty源码之编码器

highlight: arduino-light Netty如何实现自定义通信协议 在学习完如何设计协议之后&#xff0c;我们又该如何在 Netty 中实现自定义的通信协议呢&#xff1f;其实 Netty 作为一个非常优秀的网络通信框架&#xff0c;已经为我们提供了非常丰富的编解码抽象基类&#xff0c;帮助我…

C# 根据图片的EXIF自动调整图片方向

PropertyItems 代码 /// <summary>/// 根据图片exif调整方向/// </summary>/// <param name"img"></param>public void RotateImage(Bitmap img){var exif img.PropertyItems;byte orien 0;var item exif.Where(m > m.Id 274).ToArra…

16、外部配置源与外部配置文件及JSON配置

外部配置源与外部配置文件及JSON配置 application.properties application.yml 这些是配置文件&#xff0c; 命令行配置、环境变量配置、系统属性配置源&#xff0c;这些属于配置源。 外部配置源的作用&#xff1a; Spring Boot相当于对Spring框架进行了封装&#xff0c;Spri…

策略模式(C++)

定义 定义一系列算法&#xff0c;把它们一个个封装起来&#xff0c;并且使它们可互相替换((变化)。该模式使得算法可独立手使用它的客户程序稳定)而变化(扩展&#xff0c;子类化)。 ——《设计模式》GoF 使用场景 在软件构建过程中&#xff0c;某些对象使用的算法可能多种多…

viewerjs 如何新增下载图片功能(npm包补丁)

文章目录 先实现正常的效果实现下载图片改变viewerjs的build函数源码改变之后&#xff0c;执行npm i 之后node_modules源码又变回了原样 1、viwerjs所有功能都很完善&#xff0c;但唯独缺少了图片的下载 2、需求&#xff1a;在用viwerjs旋转图片后&#xff0c;可以直接下载旋转…

规划模型Matlab代码

文章目录 数学规划定义一般形式分类 1.线性规划(linear programming)2.非线性规划(nonlinear programming)3. 整数规划(integer programming)4. 0-1规划(0-1 programming)5. 最大最小化模型6. 多目标规划模型7.敏感性分析&#xff08;对权重&#xff09;[例题] 数学规划定义 数…

Stable Diffusion - SDXL 1.0 全部样式设计与艺术家风格的配置与提示词

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132072482 来源于 Anna Dittmann 安娜迪特曼&#xff0c;艺术家风格的图像&#xff0c;融合幻想、数字艺术、纹理等样式。 SDXL 是 Stable Diffus…

Git常见问题

git clone 提示OpenSSL SSL_read git clone 时提示Connection was reset, errno 10054类错误 fatal: unable to acce ss https://github.com/fex-team/ueditor.git/: OpenSSL SSL_read: Connection was reset, errno 10054 备注&#xff1a;以下方法只是归纳整理&#xff0c;…

【零基础学Rust | 基础系列 | 基础语法】变量,数据类型,运算符,控制流

文章目录 简介&#xff1a;一&#xff0c;变量1&#xff0c;变量的定义2&#xff0c;变量的可变性3&#xff0c;变量的隐藏 二、数据类型1&#xff0c;标量类型2&#xff0c;复合类型 三&#xff0c;运算符1&#xff0c;算术运算符2&#xff0c;比较运算符3&#xff0c;逻辑运算…

Apache Flink概述

Flink 是构建在数据流之上的一款有状态的流计算框架&#xff0c;通常被人们称为第三代大数据分析方案 第一代大数据处理方案&#xff1a;基于Hadoop的MapReduce 静态批处理 | Storm 实时流计算 &#xff0c;两套独立的计算引擎&#xff0c;难度大&#xff08;2014年9月&#x…

Hyperledger Fabric 使用 CouchDB 和复杂智能合约开发

前言 在上个实验中&#xff0c;我们已经实现了简单智能合约实现及客户端开发&#xff0c;但该实验中智能合约只有基础的增删改查功能&#xff0c;且其中的数据管理功能与传统 MySQL 比相差甚远。本文将在前面实验的基础上&#xff0c;将 Hyperledger Fabric 的默认数据库支持 …

Kafka3.0.0版本——Broker(Zookeeper服务端存储的Kafka相关信息)

目录 一、启动zookeeper集群及kafka集群服务启动1.1、先启动三台zookeeper集群服务&#xff0c;再启动三台kafka集群服务1.2、使用PrettyZoo连接zookeeper客户端工具 二、在zookeeper服务端存储的Kafka相关信息 一、启动zookeeper集群及kafka集群服务启动 1.1、先启动三台zook…

C++初阶引用

目录 引用引用的特性使用输出型参数作返回值小总结引用的权限引用和指针 引用 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同一块内存空间。 比如周树人&#xff0c;在外…

探索创意之路:稳定扩散AI绘画指南

文章目录 引言第一部分&#xff1a;了解稳定扩散AI绘画1.1 稳定扩散AI绘画简介1.2 稳定扩散AI绘画的优势 第二部分&#xff1a;使用稳定扩散AI绘画2.1 获取稳定扩散AI绘画工具2.2 准备绘画素材和设置参数2.3 进行AI绘画 第三部分&#xff1a;发挥创意&#xff0c;创作精彩绘画3…

阿里云AK创建

要在阿里云上创建 Access Key&#xff08;AK&#xff09;&#xff0c;您需要按照以下步骤进行操作&#xff1a; 登录到阿里云控制台&#xff08;[https://www.aliyun.com/?utm_contentse_1014243503)&#xff09;。 点击右上方的主账号&#xff0c;点击“AccessKey管理”。 …

P1064 [NOIP2006 提高组] 金明的预算方案 (依赖背包问题)(内附封面)

[NOIP2006 提高组] 金明的预算方案 题目描述 金明今天很开心&#xff0c;家里购置的新房就要领钥匙了&#xff0c;新房里有一间金明自己专用的很宽敞的房间。更让他高兴的是&#xff0c;妈妈昨天对他说&#xff1a;“你的房间需要购买哪些物品&#xff0c;怎么布置&#xff0…

R语言【Tidyverse、Tidymodel】的机器学习方法

机器学习已经成为继理论、实验和数值计算之后的科研“第四范式”&#xff0c;是发现新规律&#xff0c;总结和分析实验结果的利器。机器学习涉及的理论和方法繁多&#xff0c;编程相当复杂&#xff0c;一直是阻碍机器学习大范围应用的主要困难之一&#xff0c;由此诞生了Python…

python人工智能可以干什么,python人工智能能干什么

大家好&#xff0c;给大家分享一下python做人工智能需要什么水平&#xff0c;很多人还不知道这一点。下面详细解释一下。现在让我们来看看&#xff01; 人工智能包含常用机器学习和深度学习两个很重要的模块&#xff0c;而python拥有matplotlib、Numpy、sklearn、keras等大量的…

【深度学习笔记】深度学习框架

本专栏是网易云课堂人工智能课程《神经网络与深度学习》的学习笔记&#xff0c;视频由网易云课堂与 deeplearning.ai 联合出品&#xff0c;主讲人是吴恩达 Andrew Ng 教授。感兴趣的网友可以观看网易云课堂的视频进行深入学习&#xff0c;视频的链接如下&#xff1a; 神经网络和…

snap xxx has “install-snap“ change in progress

error description * 系重复安装&#xff0c;进程冲突 solution 展示snap的改变 然后sudo snap abort 22即可终止该进程 之后重新运行install command&#xff5e;&#xff5e; PS: ubuntu有时候加载不出来&#xff0c;执行resolvectl flush-caches&#xff0c;清除dns缓存…