快速实现用户认证:使用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_time
和account_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 数据,包含用户的
phone
和password
。 - 通过手机号查询数据库中的用户。
- 如果用户不存在,返回403错误和消息
"用户账号或密码错误"
。 - 如果用户存在,调用
check_password
函数验证密码是否正确,并检查用户状态是否为"正常"
。 - 如果验证通过,为用户生成一个新的 token(使用
generate_token
函数),更新用户的 token 字段,并提交到数据库。 - 返回包含新 token 和成功消息的 JSON 响应。
注册 (user_register
)
- 同样接收包含
phone
、password
和user_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 响应。它接收状态码、数据和消息作为参数,并返回一个 Flaskjsonify
响应。
关键工具和方法
Blueprint
:用于创建一组相关的路由和视图函数。request.json
:用于获取 JSON 格式的请求体数据。jsonify
:将数据转换为 JSON 响应。db.session
:用于数据库操作,如添加新记录和提交更改。generate_token
和user_token_required
:自定义函数和装饰器,用于处理 JWT token 的生成和验证。
整个代码展示了如何在 Flask 应用中实现用户认证和管理的基本流程,使用 JWT tokens 提供安全的用户状态管理和接口保护。
相关文章:
快速实现用户认证:使用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:…...

外汇110:外汇做空是什么意思?如何运作?一文读懂
外汇市场允许卖空,就像众多金融市场一样。但什么是卖空呢?如何外汇做空?在本文中,我们将讨论如何做空货币。什么是外汇做空? 外汇做空(Short Selling)是外汇市场上的一种投资方式。它指的是投资…...
【记录】个人博客或笔记中的数学符号设定
note 这里记录个人博客中常用的数学符号数学格式和对应含义 文章目录 note数与数组索引集合线性代数微积分概率和信息论数据与概率分布函数深度学习中的常用数学表达方式 数与数组 α 标量 α 向量 A 矩阵 A 张量 I n n 行 n 列单位矩阵 v w 单词 w 的分布式向量表示 …...
Redis Sentinel工作原理
Redis Sentinel是Redis的高可用性解决方案。它主要用来监控Redis master和slave服务器的运行状态,并在master宕机时自动进行故障转移,即从slave节点中选举出新的master节点,并让其余的slave节点指向新的master节点。 Redis Sentinel工作原理…...
GEE入门篇|遥感专业术语:理论介绍
本章的目的是介绍遥感图像的一些主要特征,以及如何在Earth Engine中检查它们。我们将讨论空间分辨率、时间分辨率和光谱分辨率,以及如何访问重要的图像元数据。将了解到来自不同卫星平台上的几个传感器的图像数据。在本章的学习完成后,您将能…...
react中如何做到中断diff过程和恢复
workLoop是 实现时间切片 和 可中断渲染的核心,简要说明如下: // 并发任务的入口function workLoopConcurrent() {// Perform work until Scheduler asks us to yield// 有任务 & 是否需要中断while (workInProgress ! null && !shouldYiel…...
python:PyPDF2 从PDF文件中提取目录
我发现 pypdf 和 pypdf2 的作者是同一人:Mathieu Fenniak pip install pypdf2 ; pypdf2-3.0.1-py3-none-any.whl (232 kB) 编写 pdf_read_dir.py 如下 # -*- coding: utf-8 -*- """ pypdf23.0.1 从PDF中提取目录 """ import os…...

Java 2:运算符、表达式和语句
2.1 运算符与表达式 Java提供了丰富的运算符,如算术运算符、关系运算符、逻辑运算符、位运算符等。Java语言中的绝大多数运算符和C语言相同,基本语句如条件分支语句,循环语句等,也和C语言类似。 2.1.1算术运算符与算术表达式 1…...
批量提取word文件中文本框内容的三种方法
一、问题的提出 在日常的办公中,有时需要提取多个word文件中的文字框的内容。有时,文字框的数量比较多,而且处于文档的不同位置,手工提取比较耗时耗力,同时也可能会产生遗漏。 我们也可以通过VBA和Python来解决这个问…...

Leecode之合并两个有序链表
一.题目及剖析 https://leetcode.cn/problems/merge-two-sorted-lists/description/ 二.思路引入 用指针遍历两个链表并实时比较,较小的元素进行尾插,然后较小元素的指针接着向后遍历 三.代码引入 /*** Definition for singly-linked list.* struct ListNode {* int va…...

陶建国教授谈中西方文化的差异与交融
龙年到来,这个春节里,“龙”字的英文翻译引发关注,冲上了热搜,网友发现,“龙”不再翻译为“dragon”,而是龙字的谐音“loong”。原来,在西方人的眼里,龙是凶猛的怪兽,具有…...

Ps:画笔选项
画笔选项 Brush Options提供了对画笔(圆形笔刷)基本属性的控制,比如大小、硬度、间距、角度和圆度等。 Photoshop 中的快速选择工具、污点修复画笔工具、修复画笔工具、颜色替换工具、背景橡皮擦工具等的工具选项栏上提供了这种圆形笔刷选项。…...

嵌入式——Flash(W25Q64)
目录 一、初识W25Q64 1. 基本认识 2. 引脚介绍 编辑 二、W25Q64特性 1. SPI模式 2. 双输出SPI方式 三、状态寄存器 1. BUSY位 2. WEL位 3. BP2、BP1、 BP0位 4. TB位 5. 保留位 6. SRP位 四、常用操作指令 1. 写使能指令(06h) 2. 写禁…...

stm32:pwm output模块,记录一下我是用smt32,输出pwm波的记录--(实现--重要)
我是实现了输出pwm波,频率固定,占空比可以不断调整的方法,将PA0接到示波器上,可以看到是一个标准的PWM波,如图下面示波器图。 1,首先是ioc的配置 我刚开始设置的分频的倍数是7199,使得分频的太大了,示波器显示不了,最后修改为71就可以,我之前设置读取pwm也是一样的…...

phpstrom创建thinkphp项目
安装php和composer 参考 安装phpstrom 创建项目 查看thinkphp版本 https://packagist.org/packages/topthink/think 打开所在项目编辑配置 即可调试运行...

【Linux】线程同步
线程同步 一、条件变量1. 同步概念2. 条件变量概念3. 条件变量接口(1)pthread_cond_init()(2)pthread_cond_destroy()(3)pthread_cond_wait()(4)pthread_cond_signal()(5…...
如何在多头自注意力机制的交叉学习中引入对于物理、生理、心理世界客观规律的对照验证...
要在多头自注意力机制的交叉学习中引入对于物理世界客观规律的对照验证,可以考虑以下方法: 1、引入物理模型 首先,建立一个物理模型,该模型能够描述物理世界中的客观规律。这个模型可以是已知的科学理论,也可以是通过实…...

智慧公厕:让智慧城市的公共厕所焕发“智慧活力”
智慧城市的建设已经进入了一个新的阶段,不仅仅是智慧交通、智慧环保,如今甚至连公厕都开始迎来智慧化时代。智慧公厕作为智慧城市的神经末梢,正在通过信息化、数字化和智慧化的方式,实现全方位的精细化管理。本文以智慧公厕源头专…...

vue导出word文档(图文示例)
第076个 查看专栏目录: VUE 本文章目录 示例说明示例效果图导出的文件效果截图示例源代码参数说明:重要提示:API 参考网址 示例说明 在Vue中导出Word文档,可以使用第三方库file-saver和html-docx-js。首先需要安装这两个库: npm …...

【C Primer Plus第六版 学习笔记】 第十七章 高级数据表示
有基础,进阶用,个人查漏补缺 链表:假设要编写一个程序,让用户输入一年内看过的所有电影,要储存每部影片的片名和评级。 #include <stdio.h> #include <stdlib.h> /* 提供malloc()的原型 */ #include <s…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
莫兰迪高级灰总结计划简约商务通用PPT模版
莫兰迪高级灰总结计划简约商务通用PPT模版,莫兰迪调色板清新简约工作汇报PPT模版,莫兰迪时尚风极简设计PPT模版,大学生毕业论文答辩PPT模版,莫兰迪配色总结计划简约商务通用PPT模版,莫兰迪商务汇报PPT模版,…...
二维FDTD算法仿真
二维FDTD算法仿真,并带完全匹配层,输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...