快速实现用户认证:使用Python和Flask配合PyJWT生成与解密Token的教程及示例代码

生成token 与解密 token 和 拦截器

#学习交流 访问
# https://v.iiar.cnimport jwt
import datetime
from models import XUser
from flask import request, jsonify
from functools import wrapsSECRET_KEY = 'XPay'# 创建token
def generate_token(user_id):try:payload = {'exp': datetime.datetime.utcnow() + datetime.timedelta(days=7),'iat': datetime.datetime.utcnow(),'sub': user_id}return jwt.encode(payload,SECRET_KEY,  # 替换为你的密钥algorithm='HS256')except Exception as e:return e# 解析token
def decode_token(token):""" 解码Token并处理异常 """try:payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])return payload['sub']  # 返回成功标志和用户IDexcept jwt.ExpiredSignatureError as e:return Falseexcept jwt.InvalidTokenError as e:return False# 查询用户状态
def check_token_and_user_status(token):user_id = decode_token(token)print(user_id)token_in_user = XUser.query.filter_by(token=token).first()# 根据是否开启多端登陆判断token是否有效multi_device_login = Trueif not multi_device_login and not token_in_user:return False, 'token过期'if user_id:user = XUser.query.get(user_id)if user:if user.state == '正常':return True, userelse:return False, '该用户状态异常,请联系客服'else:return False, '用户不存在'else:return False, 'token无效'def user_token_required(f):@wraps(f)def decorated_function(*args, **kwargs):token = request.headers.get('token')if not token:return jsonify({'code': 401,'data': '','msg': 'token不存在','time': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')})user_state, user_info = check_token_and_user_status(token)if not user_state:return jsonify({'code': 401,'data': '','msg': user_info,'time': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')})return f(*args, **kwargs, user_info=user_info)return decorated_function

详细解释

这段代码提供了一个使用 Python 和 Flask 结合 JWT (JSON Web Tokens) 进行用户认证的简单框架。它包括了生成 token、解码 token、检查用户状态和一个装饰器函数,用于保护需要认证的路由。下面是对代码的逐部分解释:

1. generate_token(user_id) 函数

  • 这个函数用于为指定的用户 ID 生成一个 JWT token。Token 包含三个重要的信息(称为payload):exp(过期时间),iat(发行时间),和sub(主题,这里用作用户 ID)。
  • Token 使用 HS256 算法进行签名,SECRET_KEY作为签名密钥。
  • Token 默认有效期为 7 天。

2. decode_token(token) 函数

  • 用于解码和验证接收到的 JWT token。如果 token 有效且未过期,这个函数返回保存在 token 的sub字段中的用户 ID。
  • 如果 token 过期(ExpiredSignatureError)或无效(InvalidTokenError),函数将返回 False。

3. check_token_and_user_status(token) 函数

  • 首先解码 token 来获取用户 ID,然后查询数据库中是否存在对应的用户和 token。
  • 如果设置了不允许多端登录(multi_device_login = False),它还会检查数据库中的 token 是否与提供的 token 匹配。
  • 根据用户的状态(如是否正常)和 token 的有效性返回相应的状态和信息。

4. user_token_required(f) 装饰器

  • 一个 Flask 路由装饰器,用于在执行实际路由函数之前进行用户认证。
  • 从请求头中获取 token,如果不存在 token 或 token 无效,则返回错误信息。
  • 如果用户认证成功,路由函数将正常执行。装饰器会将user_info(从check_token_and_user_status返回的用户信息)作为关键字参数传递给路由函数。

使用场景

  • 在需要对用户身份进行验证的 Flask 路由上,可以使用@user_token_required装饰器来确保只有携带有效 token 的请求才能访问。
  • 这套系统使得管理用户会话和访问控制变得简单,特别是在构建 RESTful API 时非常有用。

注意事项

  • 实际部署时,SECRET_KEY应当是一个安全的值,且不应该硬编码在代码中。
  • 在处理用户状态和多端登录逻辑时,需要根据实际业务需求进行调整。
  • XUser模型和数据库查询逻辑需要根据实际的数据库设计来实现。这里假设XUser是一个模型类,代表用户数据,且有一个state属性和一个token属性。

模型部分

class XUser(db.Model):id = db.Column(db.Integer, primary_key=True)mid = db.Column(db.Integer, comment='推荐人id')phone = db.Column(db.String(80), comment='手机号')user_name = db.Column(db.String(80), comment='用户昵称')openid = db.Column(db.String(120), comment='openid')password = db.Column(db.String(120), comment='密码')registration_time = db.Column(db.DateTime, default=datetime.now, comment='注册时间')token = db.Column(db.String(255), comment='Token')account_balance = db.Column(db.Numeric(20, 4), default=0.00, comment="账户余额")state = db.Column(db.String(120), default='正常', comment='用户状态')fee_percentage = db.Column(db.Integer, default=4, comment='手续费比例')def to_dict(self):return {'id': self.id,'mid': self.mid,'phone': self.phone,'user_name': self.user_name,'openid': self.openid,'registration_time': self.registration_time.strftime('%Y-%m-%d %H:%M:%S') if self.registration_time else None,'account_balance': float(self.account_balance) if self.account_balance is not None else None,'state': self.state,'fee_percentage': self.fee_percentage}

模型解释

这个XUser类是一个模型定义,使用 SQLAlchemy ORM (一个 Python SQL 工具包和对象关系映射器)用于定义和操作数据库中的用户表。每个属性(使用db.Column声明)对应用户表中的一个字段。以下是各个字段的解释:

字段解释

  • id: 用户的唯一标识符,整数类型,设为主键。
  • mid: 推荐人的ID,整数类型,用来表示这个用户是被哪个已存在的用户推荐的。
  • phone: 用户的手机号,字符串类型,最长80字符。
  • user_name: 用户昵称,字符串类型,最长80字符。
  • openid: 用户的微信OpenID,字符串类型,最长120字符。这是微信平台特有的标识用户的ID,用于识别微信用户。
  • password: 用户密码,字符串类型,最长120字符。在实际应用中,密码应该经过加密存储。
  • registration_time: 用户注册时间,DateTime类型,默认值为当前时间。这里使用了datetime.now来自动设置这个字段的值。
  • token: 用于认证的Token,字符串类型,最长255字符。这是在用户登录时生成的,用于后续请求的身份验证。
  • account_balance: 用户账户余额,数值类型,最多20位数字,小数点后最多4位。默认值为0.00。
  • state: 用户状态,字符串类型,最长120字符,默认值为’正常’。这个字段可以用来表示用户是否被禁用或其他状态。
  • fee_percentage: 手续费比例,整数类型。表示在进行某些交易时需要收取的手续费百分比,默认值为4%。

to_dict 方法

to_dict方法是一个实例方法,用于将XUser对象的属性转换成一个字典,这在进行JSON序列化时非常有用,例如在 RESTful API 响应中返回用户信息。这个方法特别处理了registration_timeaccount_balance字段,确保它们以适当的格式输出(registration_time格式化为字符串,account_balance确保为浮点数或None)。

总结

XUser类不仅定义了数据库表结构,还提供了方便的方法来操作和转换用户数据。通过使用 SQLAlchemy ORM,可以简化数据库操作,提高代码的可读性和可维护性。

用户注册/登陆/获取用户基本信息

from datetime import datetime
from models import db, XUser
from flask import request, jsonify, Blueprintfrom tools.common_method import check_password, set_password
from tools.user_token import generate_token
from tools.user_token import user_token_requireduser_api = Blueprint('user_api', __name__)# 登陆
@user_api.route('/api/user/login', methods=['POST'])
def user_login():data = request.jsonphone = data.get('phone')password = data.get('password')user = XUser.query.filter_by(phone=phone).first()print(phone)if not user:return jsonify({'code': 403,'data': '','msg': '用户账号或密码错误','time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')})else:if check_password(user.password, password) and user.state == '正常':token = generate_token(user.id)user.token = tokendb.session.commit()return jsonify({'code': 200,'token': token,'msg': '登陆成功','time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')})else:return jsonify({'code': 403,'data': '','msg': '该用户状态不允许登陆','time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')})# 注册
@user_api.route('/api/user/register', methods=['POST'])
def user_register():data = request.jsonphone = data.get('phone')password = data.get('password')user_name = data.get('user_name')password_len = len(password)phone_len = len(phone)if phone_len != 11:return jsonify({'code': 403,'data': '','msg': '注册失败,请输入11位手机号','time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')})if password_len < 6 or password_len > 32:return jsonify({'code': 403,'data': '','msg': '注册失败,密码长度请大于6位,小于32位','time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')})user = XUser.query.filter_by(phone=phone).first()if user:return jsonify({'code': 403,'data': '','msg': '注册失败,该手机已经注册,请直接登陆或更换手机后注册','time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')})else:new_password = set_password(password)new_user = XUser(phone=phone,password=new_password,user_name=user_name)db.session.add(new_user)db.session.commit()token = generate_token(new_user.id)new_user.token = tokendb.session.commit()return jsonify({'code': 200,'token': token,'msg': '注册成功','time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')})@user_api.route('/api/user/user_info', methods=['GET'])
@user_token_required
def get_user_info(user_info):return reg_func(200, user_info.to_dict(), '获取信息成功')def reg_func(code, data, msg):return jsonify({'code': code,'data': data,'msg': msg,'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S')}), code

注册/登陆/获取用户信息代码详细解释

这段代码是一个使用 Flask 框架构建的简易用户管理系统的一部分,包括用户的登录、注册以及获取用户信息的功能。它利用了 Flask 的 Blueprint 功能来组织和注册相关的路由,以及 SQLAlchemy ORM 来处理数据库操作。下面是对代码主要部分的解释:

登录 (user_login)

  • 接收客户端发送的 JSON 数据,包含用户的phonepassword
  • 通过手机号查询数据库中的用户。
  • 如果用户不存在,返回403错误和消息"用户账号或密码错误"
  • 如果用户存在,调用check_password函数验证密码是否正确,并检查用户状态是否为"正常"
  • 如果验证通过,为用户生成一个新的 token(使用generate_token函数),更新用户的 token 字段,并提交到数据库。
  • 返回包含新 token 和成功消息的 JSON 响应。

注册 (user_register)

  • 同样接收包含phonepassworduser_name的 JSON 数据。
  • 验证手机号是否为11位,密码长度是否在6到32位之间。
  • 如果手机号或密码格式不符合要求,返回403错误和相应的失败消息。
  • 如果手机号已经被注册,返回403错误和消息"注册失败,该手机已经注册,请直接登陆或更换手机后注册"
  • 如果验证通过,使用set_password函数加密密码,然后创建一个新的XUser实例,并将其添加到数据库。
  • 为新用户生成 token,更新用户的 token 字段,并提交到数据库。
  • 返回包含新 token 和成功消息的 JSON 响应。

获取用户信息 (get_user_info)

  • 这个路由使用@user_token_required装饰器,要求请求必须包含有效的 token。
  • 如果认证通过,装饰器会传递user_info参数(用户信息)给get_user_info函数。
  • 函数调用reg_func生成标准的 JSON 响应,包含用户信息和成功消息。

辅助函数 (reg_func)

  • reg_func是一个帮助函数,用于生成标准化的 JSON 响应。它接收状态码、数据和消息作为参数,并返回一个 Flask jsonify 响应。

关键工具和方法

  • Blueprint:用于创建一组相关的路由和视图函数。
  • request.json:用于获取 JSON 格式的请求体数据。
  • jsonify:将数据转换为 JSON 响应。
  • db.session:用于数据库操作,如添加新记录和提交更改。
  • generate_tokenuser_token_required:自定义函数和装饰器,用于处理 JWT token 的生成和验证。

整个代码展示了如何在 Flask 应用中实现用户认证和管理的基本流程,使用 JWT tokens 提供安全的用户状态管理和接口保护。

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

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

相关文章

如何在多头自注意力机制的交叉学习中引入对于物理、生理、心理世界客观规律的对照验证...

要在多头自注意力机制的交叉学习中引入对于物理世界客观规律的对照验证&#xff0c;可以考虑以下方法&#xff1a; 1、引入物理模型 首先&#xff0c;建立一个物理模型&#xff0c;该模型能够描述物理世界中的客观规律。这个模型可以是已知的科学理论&#xff0c;也可以是通过实…

Nginx静态内容和反向代理

文章目录 一、Nginx介绍1. 简介2. 相关网站3. 配置文件 二、location说明1. 匹配规则2. 替换匹配部分 三、Nginx代理1. Spring服务代理2. MySQL代理3. MinIO代理 一、Nginx介绍 1. 简介 Nginx&#xff08;读作“engine x”&#xff09;是一个高性能的开源HTTP和反向代理服务器…

(2.2w字)前端单元测试之Jest详解篇

Jest Jest 概述 Jest是一个领先的JavaScript测试框架&#xff0c;特别适用于React和Node.js环境。由Facebook开发&#xff0c;它以简单的配置、高效的性能和易用性而闻名。Jest支持多种类型的测试&#xff0c;包括单元测试、集成测试和快照测试&#xff0c;后者用于捕获组件或…

阿里云轻量应用服务器和ECS云服务器区别(官方文档)

阿里云轻量应用服务器和ECS云服务器有啥区别&#xff1f;轻量应用服务器是轻量级服务器&#xff0c;轻量适合个人开发者或中小企业使用&#xff0c;清理使用简单、可视化运维更容易上手&#xff1b;ECS云服务器专业级服务器&#xff0c;适合企业级应用&#xff0c;通用型、计算…

python 将普通文件转换为ts文件,用udp-ts 发送

将普通文件转换为TS文件并使用UDP发送是一个相对复杂的过程&#xff0c;因为你需要遵循TS流的格式来封装原始数据。TS流通常用于封装视频和音频数据&#xff0c;包含固定的包头和负载数据。对于简单的文本或二进制文件&#xff0c;将其转换为TS流并不常见&#xff0c;因为TS是为…

Math--API

Math 数学工具类&#xff0c;提供一些对数据进行操作的静态方法 Math类常用API 方法名说明public static int abs(int a)获取参数绝对值public static double ceil(double a)向上取整public static double floor(double a)向下取整public static int round(f…

Rust 学习笔记 - 注释全解

前言 和其他编程语言一样&#xff0c;Rust 也提供了代码注释的功能&#xff0c;注释用于解释代码的作用和目的&#xff0c;帮助开发者理解代码的行为&#xff0c;编译器在编译时会忽略它们。 单行注释 单行注释以两个斜杠 (//) 开始&#xff0c;只影响它们后面直到行末的内容…

如何在 Angular 中使用 Flex 布局

介绍 Flex Layout 是一个组件引擎&#xff0c;允许您使用 CSS Flexbox 创建页面布局&#xff0c;并提供一组指令供您在模板中使用。 该库是用纯 TypeScript 编写的&#xff0c;因此不需要外部样式表。它还提供了一种在不同断点上指定不同指令以创建响应式布局的方法。 在本教…

多数据源支持

平台倡导分布数据库&#xff0c;最简单的分库逻辑是按业务领域&#xff0c;例如人力资源系统一个库&#xff0c;客户关系管理一个库&#xff08;举个例子而已&#xff0c;在平台正式的系统中&#xff0c;人力资源系统又细分为核心库、绩效管理库、薪资管理库等&#xff09;。一…

springboot/ssm公司进销存系统Java商品销售出入库系统

springboot/ssm公司进销存系统Java商品销售出入库系统 开发语言&#xff1a;Java 框架&#xff1a;springboot&#xff08;可改ssm&#xff09; vue JDK版本&#xff1a;JDK1.8&#xff08;或11&#xff09; 服务器&#xff1a;tomcat 数据库&#xff1a;mysql 5.7&#x…

基于PPNSA+扰动算子的车间调度最优化matlab仿真,可以任意调整工件数和机器数,输出甘特图

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于PPNSA扰动算子的车间调度最优化matlab仿真,可以任意调整工件数和机器数,输出甘特图和优化收敛曲线。 2.测试软件版本以及运行结果展示 MATLAB2022a版本运行…

【JavaScript】面试手写题精讲之数组(上)

专题缘由 该专题主要是讲解我们在面试的时候碰到一些JS的手写题, 确实这种手写题还是比较恶心的。有些时候好不容易把题目写出来了&#xff0c;突然面试官冷不丁来一句有没有更优的解法&#xff0c;直接让我们僵在原地。为了解决兄弟们的这些困扰&#xff0c;这个专题于是就诞…

python入门:常用模块—jsonpickle模块

什么叫序列化&#xff1f; 序列化是指把内存里的数据类型转变成字符串&#xff0c;以使其能存储到硬盘或通过网络传输到远程&#xff0c;因为硬盘或网络传输时只能接受bytes 为什么要序列化&#xff1f; 你打游戏过程中&#xff0c;打累了&#xff0c;停下来&#xff0c;关掉…

随想录刷题笔记 —二叉树篇6 513找树左下角的值 112路径总和 106中序后序构造二叉树

513找树左下角的值 找出该二叉树的 最底层 最左边 节点的值 解法一&#xff1a;队列——层次遍历 class Solution {public int findBottomLeftValue(TreeNode root) {Queue<TreeNode> treeNodes new LinkedList<>();treeNodes.offer(root);int count 1;int re…

贪心算法之合并区间

“任世界多宽广&#xff0c;停泊在这港口~” 区间问题&#xff0c;涉及到最多的就是 取交集 和 并集的概念。我们使用C排序算法后&#xff0c;其默认规则就是按照 “左排序”进行的。因而&#xff0c;我们实质上注意的是每一个区间的 右端点&#xff0c;根据题目要求&#xff…

蓝桥杯:C++模运算、快速幂

模运算 模运算是大数运算中的常用操作。如果一个数太大&#xff0c;无法直接输出&#xff0c;或者不需要直接输出&#xff0c;则可以对它取模&#xff0c;缩小数值再输出。取模可以防止溢出&#xff0c;这是常见的操作。 模是英文mod的音译&#xff0c;取模实际上是求余。 取…

表达式 副作用 序列点

语句分类 标号语句(标签&#xff0c;常与goto配合使用)复合语句(块)表达式语句(赋值表达式语句、函数表达式语句等)选择语句迭代语句(循环)跳转语句(return,break,continue) 其中复合语句(块)可视为单个语句。因此while和for循环之后加的是单个语句(简单语句、复合语句、空语…

树莓派:使用mdadm为重要数据做RAID 1保护

树莓派作为个人服务器可玩性还是有点的。说到服务器&#xff0c;在企业的生成环境中为了保护数据&#xff0c;基本上都会用到RAID技术。比如&#xff0c;服务器两块小容量但高性能的盘做个RAID-1按装操作系统&#xff0c;余下的大容量中性能磁盘做个RAID-5或者RAID-6存放数据。…

网络原理(HTTP篇)

网络原理HTTP 前言HTTPHTTP的工作流程抓包工具抓取HTTP报文HTTP报文格式 请求报文具体细节首行URLURL的基本格式URL encode 方法 报头(header)HostContent-Length 和 Content-TypeUser-Agent&#xff08;UA&#xff09;RefererCookie&#xff08;重要&#xff09; 前言 如图&a…

HAL/LL/STD STM32 U8g2库 +I2C SSD1306/sh1106 WouoUI磁贴案例

HAL/LL/STD STM32 U8g2库 I2C SSD1306/sh1106 WouoUI磁贴案例 &#x1f4cd;基于STM32F103C8T6 LL库驱动版本&#xff1a;https://gitee.com/chcsx/platform-test/tree/master/MDK-ARM&#x1f3ac;视频演示&#xff1a; WouoUI移植磁贴案例&#xff0c;新增确认弹窗 &#x1f…