快速实现用户认证:使用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…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
