快速实现用户认证:使用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…...
微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...
nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...
精益数据分析(98/126):电商转化率优化与网站性能的底层逻辑
精益数据分析(98/126):电商转化率优化与网站性能的底层逻辑 在电子商务领域,转化率与网站性能是决定商业成败的核心指标。今天,我们将深入解析不同类型电商平台的转化率基准,探讨页面加载速度对用户行为的…...
python基础语法Ⅰ
python基础语法Ⅰ 常量和表达式变量是什么变量的语法1.定义变量使用变量 变量的类型1.整数2.浮点数(小数)3.字符串4.布尔5.其他 动态类型特征注释注释是什么注释的语法1.行注释2.文档字符串 注释的规范 常量和表达式 我们可以把python当作一个计算器,来进行一些算术…...
