flask中的flask-login

news2024/11/15 8:35:18

在这里插入图片描述

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 LoginManager

login_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 SQLAlchemy

db = 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 here
    pass

那么登录视图的端点名就是 ‘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 DataRequired

class 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, EqualTo

class 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_app

class 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')

    @staticmethod
    def verify_reset_token(token):
        s = Serializer(current_app.config['SECRET_KEY'])
        try:
            user_id = s.loads(token)['user_id']
        except:
            return None
        return User.query.get(user_id)
  1. 创建一个发送密码重置电子邮件的函数

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

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

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

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

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

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

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

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

count(列名) ,count(1)与count(*) 有何区别?

Mysql版本&#xff1a;8.0.26 可视化客户端&#xff1a;sql yog 文章目录 一、Mysql之count函数简介二、count(列名) &#xff0c;count(常量)与count(*) 有何区别&#xff1f;2.1 统计字段上的区别2.2 执行效率上的区别 一、Mysql之count函数简介 &#x1f449;表达式 COUNT(…

DP-GAN损失

在前面我们看了生成器和判别器的组成。 生成器损失公式&#xff1a; 首先将fake image 和真实的 image输入到判别器中&#xff1a; 接着看第一个损失&#xff1a;参数分别为fake image经过判别器的输出mask&#xff0c;和真实的label进行损失计算。对应于&#xff1a; 其中l…

动态规划之树形DP

动态规划之树形DP 树形DP何为树形DP 树形DP例题HDU-1520 Anniversary partyHDU-2196 Computer834. 树中距离之和 树形DP 何为树形DP 树形DP是指在“树”这种数据结构上进行的动态规划&#xff1a;给出一颗树&#xff0c;要求以最少的代价&#xff08;或取得最大收益&#xff…

Vue-前端工程化

前后端开发模式 早期开发是前后端混合开发 即前后端代码写在一个工程中 前端写完给后端&#xff0c;后端发现问题反映给前端&#xff0c;后端就需要懂全栈 YAPI&#xff08;接口在线管理平台&#xff09; 一个接口管理和编辑平台 现在已经没有在维护了 还有mock服务 就是根据…

leetcode 912.排序数组

⭐️ 题目描述 &#x1f31f; leetcode链接&#xff1a;排序数组 思路&#xff1a; 此题如果使用冒泡插入选择这些时间复杂度 O ( N 2 ) O(N^2) O(N2) 的算法会超时&#xff0c;使用快排 优化也过不去&#xff0c;因为里面有一个测试用例全是 2 即使加了三数取中也会是 O (…

Java I/O模型

目录 一、介绍I/O 二、Java中常见的I/O 1.BIO&#xff0c;同步阻塞IO 2.NIO&#xff0c;同步非阻塞IO 3.AIO&#xff0c;异步I/O 三、三种IO的区别 一、介绍I/O 1.I/O&#xff08;Input/Output&#xff09;的即为输入输出。 2.从计算机的角度来看&#xff1a;在冯诺伊曼…

Vector - CAPL - 诊断模块函数(连接配置)

CanTpGetMaximumReceiveLength & CanTpSetMaximumReceiveLength 功能&#xff1a;获取或设置该节点接收数据时可接受的最大长度&#xff1b;如果指示较长数据块的第一帧到达&#xff0c;则溢出 (FC.Ovflw) 流状态流控制帧将被发送回发送器。 注意&#xff1a;CANoe 支持高…

NOsql之MongoDB入门分享

目录 一、MongoDB简介 1、概念理解 2、yum安装部署 3、二进制安装部署 4、配置文件解析 二、MongoDB基本管理 1、登录操作 2、管理命令 3、用户管理 一、MongoDB简介 1、概念理解 关系型数据库&#xff08;RDBMS:Relational Database Management System) MySql、Ora…

YOLO实战1.2-YOLOV5人脸检测

上个项目实现了车牌的检测和识别&#xff0c;这次实现一个简单的人脸检测(加口罩)项目 一.数据集 使用1200张图片进行训练 400张进行测试 二.各项指标 三.效果

SpringCloud Gateway 在微服务架构下的最佳实践

作者&#xff1a;徐靖峰&#xff08;岛风&#xff09; 前言 本文整理自云原生技术实践营广州站 Meetup 的分享&#xff0c;其中的经验来自于我们团队开发的阿里云 CSB 2.0 这款产品&#xff0c;其基于开源 SpringCloud Gateway 开发&#xff0c;在完全兼容开源用法的前提下&a…

云服务器开放端口

文章目录 云服务器开放端口1. 云服务器后台开放端口2. linux系统开放端口2.1 查看防火墙状态2.2 开启防火墙2.3 开放端口&#xff08;以端口2000为例&#xff09;2.4 重新载入防火墙2.5 查看已开放的端口2.6 重启防火墙2.7 关闭端口 云服务器开放端口 本篇文章主要以阿里云服务…

Pandas.rank() 函数详解

文章目录 Pandas.rank() 函数详解一、参数解析二、案例分享默认排名降序: ascending Falsemethod minmethod maxmethod firstmethod densena_optionbottompct True Pandas.rank() 函数详解 一、参数解析 method&#xff1a;指定排名时的策略。 默认值为 average&#x…

[python]conda激活环境后pip -V显示在base路径

正常激活环境后pip -V是在激活环境路径&#xff0c;比如 但是我的突然确为 D:\anaconda3\lib\site-packages里面&#xff0c;百思不得其解&#xff0c;后来发现是我在环境变量加了PYTHONHOME环境变量&#xff0c;如果你的环境变量有PYTHONHOME或者PYTHONPATH请删掉试试。 此外…

Java并发系列之二:悲观锁机制

什么是锁 在并发环境下&#xff0c;会出现多个线程对同一个资源进行争抢的情况&#xff0c;假设A线程对资源正在进行修改&#xff0c;此时B线程此时又对资源进行了修改&#xff0c;这就可能会导致数据不一致的问题。为了解决这个问题&#xff0c;很多编程语言引入了锁机制&…

Stephen Wolfram:机器学习与神经网络训练

Machine Learning, and the Training of Neural Nets 机器学习与神经网络训练 We’ve been talking so far about neural nets that “already know” how to do particular tasks. But what makes neural nets so useful (presumably also in brains) is that not only can t…

【前端知识】React 基础巩固(四十六)——自定义Hook的应用

React 基础巩固(四十六)——自定义Hook的应用 一、自定义Hook的应用 自定义Hook本质上只是一种函数代码逻辑的抽取&#xff0c;严格意义上而言&#xff0c;它并不算React的特性。 实现组件创建/销毁时打印日志 import React, { memo, useEffect, useState } from "react…

#P0994. [NOIP2004普及组] 花生采摘

题目描述 鲁宾逊先生有一只宠物猴&#xff0c;名叫多多。这天&#xff0c;他们两个正沿着乡间小路散步&#xff0c;突然发现路边的告示牌上贴着一张小小的纸条&#xff1a;“欢迎免费品尝我种的花生&#xff01;――熊字”。 鲁宾逊先生和多多都很开心&#xff0c;因为花生正…

java学习路程之篇五、进阶知识、常用API、Object类、Math类、System类、BigDecimal类、包装类

文章目录 1、介绍2、Object类3、Math类4、System类5、BigDecimal类6、包装类 1、介绍 2、Object类 3、Math类 4、System类 5、BigDecimal类 6、包装类

华为云低代码平台Astro Canvas 搭建汽车展示大屏——实验指导手册

实验背景 大屏应用Astro Canvas是华为云低代码平台Astro的子服务之一&#xff0c;是以数据可视化为核心&#xff0c;以屏幕轻松编排&#xff0c;多屏适配可视为基础&#xff0c;用户可通过图形化界面轻松搭建专业水准的数据可视化大屏。例如汽车展示大屏、监控大屏、项目开发大…

【Docker】Docker安装Consul

文章目录 1. 什么是Consul2. Docker安装启动Consul 点击跳转&#xff1a;Docker安装MySQL、Redis、RabbitMQ、Elasticsearch、Nacos等常见服务全套&#xff08;质量有保证&#xff0c;内容详情&#xff09; 1. 什么是Consul Consul是HashiCorp公司推出的开源软件&#xff0c;提…