【python实用小脚本-118】基于Flask的用户认证系统:app.py、forms.py与user.py解析

在当今的网络应用中,用户认证是一个不可或缺的功能。无论是社交平台、电商平台还是企业管理系统,都需要确保只有授权用户才能访问特定的资源。本文将详细介绍一个基于 Flask 框架的用户认证系统,该系统由三个主要文件组成:app.pyforms.pyuser.py。通过解析这三个文件,我们将深入了解如何实现一个安全、高效的用户注册、登录和注销功能。

一、系统概述

这个用户认证系统使用 Flask 框架构建,Flask 是一个轻量级的 Python Web 框架,以其灵活性和易于扩展而受到开发者的喜爱。系统的主要功能包括用户注册、登录、注销以及访问控制。用户注册时需要填写个人信息,包括用户名、密码、邮箱等。登录时,系统会验证用户输入的用户名和密码是否正确。一旦用户登录成功,他们可以访问受保护的页面,如个人仪表盘。用户注销后,将无法再访问这些受保护的页面,直到重新登录。

二、代码功能详细分析

(一)app.py:Flask 应用的入口

app.py 是整个 Flask 应用的入口文件,它负责初始化 Flask 应用、定义路由和视图函数,并启动服务器。

from flask import Flask, render_template, flash, redirect, session
from functools import wraps
import setup.config as config
from user import Userapp = Flask(__name__, template_folder="templates", static_folder='static')

在代码的开头,我们导入了必要的模块和类。Flask 是 Flask 框架的核心类,render_template 用于渲染 HTML 模板,flash 用于显示消息提示,redirect 用于重定向用户到其他页面,session 用于管理用户会话。wraps 是一个装饰器,用于保留原始函数的元信息。setup.config 是一个配置模块,包含了数据库配置和其他应用配置。User 类包含了用户注册、登录和注销的逻辑。

接下来,我们定义了一个名为 login_required 的装饰器,用于保护需要用户登录才能访问的路由。

def login_required(f):@wraps(f)def wrap(*args, **kwargs):if 'logged_in' in session:return f(*args, **kwargs)else:flash('Unauthorized. Please login.', 'danger')return redirect('/')return wrap

这个装饰器检查用户是否已经登录(即 session 中是否存在 logged_in)。如果用户已经登录,它将正常执行视图函数;否则,它会显示一个错误消息,并将用户重定向到登录页面。

然后,我们定义了三个路由://logout/dashboard

@app.route('/', methods=['POST', 'GET'])
def register():return User().register()@app.route('/logout')
def logout():return User().logout()@app.route('/dashboard')
@login_required
def dashboard():return render_template('dashboard.html')

/ 路由是用户注册和登录的页面,它调用了 User 类的 register 方法。/logout 路由用于用户注销,它调用了 User 类的 logout 方法。/dashboard 路由是用户登录后的仪表盘页面,它使用了 login_required 装饰器来保护页面,只有登录用户才能访问。

最后,我们启动了 Flask 应用。

if __name__ == "__main__":app.secret_key = config.secret_keyapp.run()

我们从配置模块中获取了 secret_key,并将其设置为 Flask 应用的密钥。然后,我们调用了 app.run() 来启动服务器。

(二)forms.py:表单定义

forms.py 文件定义了用户注册和登录所需的表单。它使用了 WTForms 库,这是一个功能强大的表单处理库,支持各种类型的字段和验证器。

from wtforms import Form, StringField, PasswordField, validators, SubmitField

我们导入了 Form 类以及所需的字段类型和验证器。

首先,我们定义了 registerForm 类,用于用户注册。

class registerForm(Form):name = StringField('',[validators.DataRequired(), validators.Length(min=1, max=50)],render_kw={"placeholder": "Name"})username = StringField('',[validators.Length(min=4, max=25)],render_kw={"placeholder": "Username"})email = StringField('',[validators.Length(min=6, max=150)],render_kw={"placeholder": "Email"})password = PasswordField('', [validators.DataRequired(),validators.EqualTo('confirm', message="Passwords do not match!")], render_kw={"placeholder": "Password"})confirm = PasswordField('', render_kw={"placeholder": "Confirm Password"})submit1 = SubmitField('Register')

registerForm 包含了用户注册所需的所有字段:nameusernameemailpasswordconfirm。每个字段都使用了相应的验证器,例如 DataRequired 确保字段不为空,Length 确保字段长度符合要求,EqualTo 确保密码和确认密码一致。render_kw 参数用于设置字段的 HTML 属性,例如占位符文本。

接下来,我们定义了 loginForm 类,用于用户登录。

class loginForm(Form):username = StringField('', render_kw={"placeholder": "Username"})password = PasswordField('', [validators.DataRequired()], render_kw={"placeholder": "Password"})submit2 = SubmitField('Login')

loginForm 包含了用户登录所需的字段:usernamepasswordusername 字段没有使用验证器,因为用户名可以为空(在实际应用中,你可能希望添加验证器来确保用户名不为空)。password 字段使用了 DataRequired 验证器,确保用户输入了密码。submit2 是一个提交按钮字段。

(三)user.py:用户逻辑处理

user.py 文件包含了用户注册、登录和注销的逻辑。它使用了 FlaskWTForms,以及 passlib 库来处理密码加密和验证。

from flask import render_template, flash, redirect, session, request
from forms import registerForm, loginForm
from passlib.hash import sha256_crypt
import setup.config as config
import uuid

在代码的开头,我们导入了必要的模块和类。render_templateflashredirectsession 是 Flask 提供的函数和对象,用于处理模板渲染、消息提示、重定向和用户会话。registerFormloginForm 是我们在 forms.py 中定义的表单类。sha256_cryptpasslib 库提供的密码加密和验证工具。setup.config 是配置模块,包含了数据库配置和其他应用配置。uuid 是一个用于生成唯一标识符的模块。

接下来,我们定义了 User 类。

class User:def start_session(self, user):del user['password']session['logged_in'] = Truesession['user'] = user

User 类包含了一个名为 start_session 的方法,用于启动用户会话。它从用户字典中删除了密码字段,然后将 logged_in 设置为 True,并将用户信息存储在 session 中。

然后,我们定义了 register 方法,用于处理用户注册。

def register(self):reg_form = registerForm(request.form)login_form = loginForm(request.form)if request.method == "POST":if reg_form.submit1.data and reg_form.validate():user = {"_id": uuid.uuid4().hex,"name": reg_form.name.data,"email": reg_form.email.data,"username": reg_form.username.data,"password": reg_form.password.data}user['password'] = sha256_crypt.encrypt(user['password'])if config.db.users.find_one({"email": user['email']}):error = "Email already exists!"return render_template(config.template,error=error,reg_form=reg_form,login_form=login_form)if config.db.users.insert_one(user):self.start_session(user)flash('You are now registered and can log in!', 'success')return render_template(config.template,reg_form=reg_form,login_form=login_form)elif login_form.submit2.data and login_form.validate():user = config.db.users.find_one({"username": login_form.username.data})if user:if sha256_crypt.verify(login_form.password.data, user['password']):self.start_session(user)return render_template('dashboard.html')else:error = 'Incorrect login details!'return render_template(config.template,error=error,reg_form=reg_form,login_form=login_form)else:error = 'Username not found!'return render_template(config.template,error=error,reg_form=reg_form,login_form=login_form)error = 'Check the registered details!'return render_template(config.template,error=error,reg_form=reg_form,login_form=login_form)else:try:return render_template(config.template,reg_form=reg_form,login_form=login_form)except Exception:return "Given template does not exists."

register 方法首先创建了 registerFormloginForm 的实例。如果请求方法是 POST,它会检查用户是否提交了注册表单或登录表单。如果用户提交了注册表单并且表单验证通过,它会创建一个用户字典,包含用户的基本信息和加密后的密码。然后,它会检查数据库中是否已经存在该用户的邮箱,如果存在,它会显示一个错误消息。如果不存在,它会将用户信息插入数据库,并启动用户会话。如果用户提交了登录表单并且表单验证通过,它会从数据库中查找用户,如果用户存在并且密码匹配,它会启动用户会话并将用户重定向到仪表盘页面。如果密码不匹配或用户不存在,它会显示一个错误消息。

最后,我们定义了 logout 方法,用于处理用户注销。

def logout(self):session.clear()flash("You are now logged out!", "success")return redirect('/')

logout 方法清除了用户会话,并显示一个成功消息,然后将用户重定向到登录页面。

三、总结

通过解析 app.pyforms.pyuser.py 这三个文件,我们深入了解了一个基于 Flask 框架的用户认证系统的实现细节。这个系统使用了 Flask 的会话管理、WTForms 的表单处理和 passlib 的密码加密功能,实现了用户注册、登录、注销和访问控制。在实际应用中,你可以根据自己的需求对这个系统进行扩展和优化,例如添加更多的用户信息字段、使用更复杂的密码加密算法、实现用户角色管理等。

源码获取

完整代码已开源,包含详细的注释文档:
🔗 [GitCode仓库] https://gitcode.com/laonong-1024/python-automation-scripts
📥 [备用下载] https://pan.quark.cn/s/654cf649e5a6 提取码:f5VG

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

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

相关文章

phpstudy apache伪静态.htaccess文件置空丢失问题解决

phpstudy apache伪静态.htaccess文件置空丢失 在使用phpstudy本地部署项目的时候,创建网站-根目录选择public等运行目录,并且点击确认后,会碰到原本项目中的apache伪静态.htaccess文件被置空丢失的问题,导致项目无法正常访问。 解…

【thinkphp5】Session和Cache记录微信accesstoken

记录一个项目实际遇到的坑,不要把token存放在session,要存在在cache里面!! 因为Session并不能设置expire过期时间,Session::set()方法第三个参数是作用域,而非过期时间!!&#xff0…

网络协议完全指南:从HTTP长短连接到TCP-UDP的深度对话

🌐 网络协议完全指南:从HTTP长短连接到TCP-UDP的深度对话 本文采用对话形式,通过小李和小王的问答,深入浅出地讲解网络协议、长短连接等核心概念,帮助读者建立完整的网络知识体系。 引言 在Java后端开发中&#xff0c…

04-StarRocks集群运维FAQ

StarRocks集群运维FAQ 概述 本文档整理了StarRocks集群运维过程中常见的问题和解决方案,涵盖了集群管理、节点维护、监控告警、故障处理等各个方面,帮助运维人员高效管理StarRocks集群。 集群管理FAQ Q1: 如何查看集群状态? A: 集群状态查看方法: 1. 查看FE节点状态 …

通过Prompt提示构建思维链

《DEEPSEEK原生应用与智能体开发实践 王晓华 书籍 图书》【摘要 书评 试读】- 京东图书 思维链技术开启了人工智能通向人类智能的崭新路径。它让模型不再仅仅是机械地执行指令,而是开始具备类似人类的思考方式,能够理解问题的本质,进行深层次…

OpenCV边缘填充方式详解

一、边缘填充概述 在图像处理中,边缘填充(Border Padding)是一项基础而重要的技术,特别是在进行卷积操作(如滤波、边缘检测等)时,处理图像边缘像素需要用到周围的像素值。由于图像边缘的像素没…

如何评估RAG系统?全面指标体系

构建一个可靠的 检索增强生成(Retrieval-Augmented Generation, RAG)系统,不仅要关注模型的构建,更重要的是对系统性能进行科学、系统的评估。评估不仅衡量系统的效果,也为迭代优化提供依据。 本文将围绕 RAG 系统的评…

力扣-合并区间

题目 56. 合并区间 - 力扣&#xff08;LeetCode&#xff09; 解析: 先按开始维度排序&#xff0c;之后依次合并&#xff0c;如果开头 < 当前区间的最后就合并&#xff0c;> 就开辟新区间 代码: class Solution {public int[][] merge(int[][] intervals) {int n in…

【软考高级系统架构论文】论基于构件的软件开发方法及其应用

论文真题 基于构作的 软件开发 (Component-Based Software Development,CBSD) 是一种基于分布对象技术、强调通过可复用构件设计与构造软件系统的软件复用途径。基于构件的软件系统中的构件可以是COTS (Commercial-Off-the-Shelf) 构件,也可以是通过其它途径获得的构件(如自…

recipes的版本比较老如何更新到新版本?

在 Yocto 项目中,当你发现 “meta-openembedded” 层中的某些 recipe 版本太旧,而你想使用更新版本时,最佳实践是在你自己项目的自定义层 (custom layer) 中使用 “bbappend” 文件进行覆盖或升级。 核心思路: 不要直接修改 “meta-openembedded” 层的 recipe ( “*.bb”…

【软件系统架构】系列四:嵌入式软件-NPU(神经网络处理器)系统及模板

目录 一、什么是 NPU? 二、NPU 与 CPU/GPU/DSP 对比 三、NPU 的工作原理 核心结构: 数据流架构: 四、NPU 芯片架构(简化图) 五、NPU 的优势 六、NPU 应用场景 视觉识别 语音识别 自动驾驶 智能监控 AIoT 设备 七、主流 NPU 芯片/架构实例 八、开发者工具生…

【NLP】使用 LangGraph 构建 RAG 的Research Multi-Agent

本文中&#xff0c;我们介绍了一个使用LangGraph开发的RAG的Research Multi-Agent工具的实际项目。该工具旨在解决需要多个来源和迭代步骤才能得出最终答案的复杂问题。它使用混合搜索和rerank步骤来检索文档&#xff0c;还结合了自我纠正机制&#xff0c;包括幻觉检查过程&…

【Docker基础】Docker容器管理:docker restart详解

目录 1 docker restart命令概述 1.1 命令作用 1.2 与相关命令对比 2 命令语法详解 2.1 基础语法 2.2 核心参数说明 3 核心原理深度解析 3.1 信号传递机制 3.2 状态转换 4 典型应用场景 4.1 服务配置更新 4.2 故障恢复流程 5 进阶使用技巧 5.1 组合命令应用 5.2 …

mongoDB服务本地化部署

mongoDB服务本地化部署 前言mongoDB下载选择版本安装 前言 mongoDB数据库解释 MongoDB 是由C语言编写的&#xff0c;是一个基于分布式文件存储的开源数据库系统&#xff1b;在高负载的情况下&#xff0c;添加更多的节点&#xff0c;可以保证服务器性能&#xff1b;MongoDB 旨在…

YOLOv10tensorRT推理代码C++

最近实现了YOLOv10的tensorRT推理代码除了后处理部分只适合YOLOv10之外&#xff0c;其余部分基本可以在yolo系列通用~学习记录~。 #include <fstream> #include <iostream> #include <vector> #include <opencv2/opencv.hpp> #include "NvInfer.…

软件定时器详解:RTOS 中的“软时钟”机制与源码解析

在嵌入式实时系统开发中&#xff0c;定时器是不可或缺的工具。软件定时器&#xff08;Software Timer&#xff09; 提供了一种无需创建独立任务、便可在特定延时后执行回调函数的机制。它适用于那些不要求高精度、但需要周期性或一次性延时执行操作的场景。 一、什么是软件定时…

从Yocto中获取源码用传统的方式单独编译

要获取 Yocto 构建后的 Linux 内核和 U-Boot 源码,并进行独立编译,需获取完整的源码树(包含所有应用补丁和配置)及原始配置信息。以下是具体步骤: 获取最终源码路径确定构建目录位置: 内核工作目录 KERNEL_WORKDIR=$(bitbake -e virtual/kernel | grep ^WORKDIR= | cut…

【记录】服务器|常见的八种硬盘接口的简介和清晰的接口图片(2025年6月)

硬盘接口很多&#xff0c;在管服务器的时候总是要买&#xff0c;但是偶尔会忘记自己的服务器支持什么接口&#xff0c;此时就需要看引脚。 如果没插满&#xff0c;就可以直接拍接口的图片&#xff0c;与下面这些图片对照一下【文字介绍是AI直接生成的&#xff0c;图片是我到处…

在一个成熟产品中,如何设计数据库架构以应对客户字段多样化,确保系统的可维护性、可扩展性和高性能。

在SaaS系统、平台型应用或高度可配置的企业级软件中&#xff0c;我们常常会遇到一个现实问题&#xff1a;不同客户对同一个业务表存在差异化字段需求。例如&#xff0c;A客户需要一个“业务员等级”字段&#xff0c;B客户不需要&#xff1b;C客户希望订单表中增加“海外仓编码”…

社群营销应该怎么玩

现在做营销&#xff0c;光靠打广告可不行了。大家都喜欢扎堆儿&#xff0c;找志同道合的人一起玩&#xff0c;这就是社群的力量。那怎么用好这股力量呢&#xff1f;咱们慢慢聊。 首先得明白&#xff0c;社群不是拉个群就完事了。关键是要让大家觉得这里有意思&#xff0c;有收…