flask 之JWT认证实现

目录

1、JWT

1.1、JWT概述

1.2、token的生成

1.3、token校验

1.4、flask项目中实现JWT认证

1、JWT

1.1、JWT概述

JWT(JSON Web Token)是一种用于身份验证和授权的开放标准。它由三部分组成,分别是头部、负载和签名。

头部(Header)是一个 JSON 对象,描述了使用的算法和类型。它通常包含两个字段:算法(alg)和类型(typ)。

负载(Payload)也是一个 JSON 对象,用于存储用户的相关信息。它可以包含一些预定义的字段,如过期时间(exp)、发布时间(iat)等,也可以包含一些自定义字段。

签名(Signature)使用指定的算法对头部和负载进行加密,生成一段字符串。这个字符串可以用于验证数据的完整性。

1、传统的token认证流程

  1. 用户登录:用户输入用户名和密码,向服务器发送登录请求。
  2. 生成token:服务器验证用户名和密码的正确性,如果验证通过,则生成一个随机字符串作为token,并将这个token与用户ID等关键信息关联起来(例如,将token和用户ID作为键值对存储在Redis等缓存中)。
  3. 返回token:服务器将生成的token返回给客户端,客户端将token保存在cookie或localStorage中。
  4. 携带token:当客户端需要访问需要认证的接口时,会在请求头中携带这个token。
  5. 验证token:服务器在接收到请求后,会从请求头中提取token,并根据token在缓存中查找对应的用户信息。如果找到了对应的用户信息,则说明用户已经登录且token有效;否则,说明用户未登录或token已过期。

2、传统token认证流程和JWT的对比

  1. 存储方式:传统token方式需要将token保存在服务器端(如Redis),而JWT则将token的所有信息都包含在token本身中,无需在服务器端保存。
  2. 安全性:JWT通过签名机制来确保数据的完整性和防止篡改,而传统token方式则更依赖于服务器端的验证。
  3. 应用场景:JWT更适用于分布式系统或跨域请求的场景,而传统token方式则更适用于传统的Web应用。

1.2、token的生成

jwt的生成token格式如下,即:由 . 连接的三段字符串组成。

eyJhbGciOiJIUzI1NiIsInR5cCI6Imp3dCJ9.eyJ1c2VybmFtZSI6ImxqIiwiZXhwIjoxNzE2NzkyODI4fQ.WrT1XY8CC1vFo8tPpt0ZrDjje5ooD8hTOvIW42Z2WEo

1、生成规则如下:

  • token组成:将三段字符串通过 . 拼接起来就生成了jwt的token。
  • 第一段HEADER部分,固定包含算法和token类型,对此json进行base64url加密,这就是token的第一段。
headers = {'typ': 'jwt','alg': 'HS256'
}
  • 第二段PAYLOAD部分,包含一些数据,对此PAYLOAD进行base64url加密,这就是token的第二段
payload = {'user_id':1,'username':'张三', 'role':'admin','exp': "XXX"...........
}
  • 第三段SIGNATURE部分,把前两段的base密文通过.拼接起来,然后对其进行HS256加密,再然后对hs256密文进行base64url加密,最终得到token的第三段。
base64url(HMACSHA256(base64UrlEncode(headers) + "." + base64UrlEncode(payload),secret # 秘钥加盐)
)

注意:base64url加密是先做base64加密,然后再把 - 替换 + _ 替换 / 。

2、代码实现:

  • 使用的库是:pyjwt模块。
  • 安装库:

pip install pyjwt

代码实现:

import jwt
import datetime# 秘钥加盐
SALT = 'adasfasfgthfafklsaj?lkasld;)(hjasgbsvbfjh='def create_token():# headerheaders = {'typ': 'jwt','alg': 'HS256'}# payloadpayload = {'user_id': 1,  # 自定义用户ID'username': '张三',  # 自定义用户名'role': "admin", # 自定义角色'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=2)  # 过期时间(2个小时)}result = jwt.encode(headers=headers, payload=payload, key=SALT, algorithm=["HS256"])return resultif __name__ == '__main__':token = create_token()print(token)

1.3、token校验

获取token之后,会按照以下步骤(主要是进行超时和合法性校验)进行校验:

  • 将token分割成 header_segment、payload_segment、crypto_segment 三部分
  • 对第一部分header_segment进行base64url解密,得到header
  • 对第二部分payload_segment进行base64url解密,得到payload
  • 对第三部分crypto_segment进行base64url解密,得到signature后进行合法性校验。
    • 拼接前两段密文,即:signing_input
    • 从第一段明文中获取加密算法,默认:HS256
    • 使用 算法+盐 对signing_input 进行加密,将得到的结果和signature密文进行比较。

代码实现:

import jwt# 秘钥加盐
SALT = 'adasfasfgthfafklsaj?lkasld;)(hjasgbsvbfjh='def get_payload(token):try:# 校验token合法性和是否超时verified_payload = jwt.decode(jwt=token, key=SALT, verify=True, algorithms=["HS256"])return verified_payloadexcept jwt.ExpiredSignatureError:print("token已过期")except jwt.DecodeError:print('token认证失败')except jwt.InvalidTokenError:print('非法的token')if __name__ == '__main__':token = "eyJhbGciOiJIUzI1NiIsInR5cCI6Imp3dCJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6Ilx1NWYyMFx1NGUwOSIsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcxNzQwMDIwMn0.iXqTAykKdA8ln0WMCsdhcc3Je0l4qOvYoxctkjEmhHs"payload = get_payload(token)print(payload)

1.4、flask项目中实现JWT认证

项目的目录结构如下:

1、app.py文件

#!/usr/bin/env python
# -*- coding:utf-8 -*-import base64
from flask import Flask, request, jsonify, g
from utils.jwt_auth import create_token, check_tokenapp = Flask(__name__)# 通过url传递token
# 每一个请求前都进行token的验证
# @app.before_request
# def jwt_query_params_auth():
#     if request.path == '/login/':
#         return
#     token = request.args.get('token')
#     result = check_token(token)
#     if not result['status']:
#         return jsonify(result)
#     g.user_info = result['info']# 通过Authorization请求头传递token@app.before_request
def jwt_authorization_auth():if request.path == '/login/':return# 在实际项目中Authorization的组成一般是: Bearer toeknauthorization = request.headers.get('Authorization', '')token = ""# 对head进行解密if authorization:# 获取token信息token = authorization.split(" ")[1]# 获取token中的header加密部分encoded_header = token.split(".")[0]# 注意:我们需要替换字符并确保字符串长度是 4 的倍数padded = encoded_header + '=' * (-len(encoded_header) % 4)# 对header进行base64url解密header = base64.urlsafe_b64decode(padded.replace('-', '+').replace('_', '/')).decode('utf-8')print(header)result = check_token(token)if not result['status']:return jsonify(result)g.user_info = result['info']@app.route('/login/', methods=['POST'])
def login():user = request.form.get('username')pwd = request.form.get('password')print(user)# 检测用户和密码是否正确,此处可以在数据进行校验。if user == '张三' and pwd == '123456':# 用户名和密码正确,给用户生成token并返回token = create_token({'user_id':1, 'username':'张三', 'role':'admin'})return jsonify({'status': True, 'token': token})return jsonify({'status': False, 'error': '用户名或密码错误!'})@app.route('/info/')
def order():print(g.user_info)return jsonify(g.user_info)if __name__ == '__main__':app.run(debug=True)

2、jwt_auth.py文件

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import jwt
import datetime# 秘钥加盐
SALT = 'adasfasfgthfafklsaj?lkasld;)(hjasgbsvbfjh='def create_token(payload, timeout=60):""":function: 创建token:param payload:  例如:{'user_id':1,'username':'张三', 'role':'admin'}用户信息:param timeout: token的过期时间,默认60分钟:return:"""headers = {'typ': 'jwt','alg': 'HS256'}payload['exp'] = datetime.datetime.utcnow() + datetime.timedelta(minutes=timeout)result = jwt.encode(headers=headers, payload=payload, key=SALT, algorithm="HS256")return resultdef check_token(token):""":function: 检验token的合法性和是否过期:param token: 用户token信息:return: 返回检验结果"""result = {'status': False, 'info': None, 'msg': None}try:print(token)verified_payload = jwt.decode(jwt=token, key=SALT, verify=True, algorithms=["HS256"])result['status'] = Trueresult['info'] = verified_payloadexcept jwt.ExpiredSignatureError:result['msg'] = 'token已失效'except jwt.DecodeError:result['msg'] = 'token认证失败'except jwt.InvalidTokenError:result['msg'] = '非法的token'return result

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

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

相关文章

最新鲸发卡v11.61开心版 无后门发卡平台源码

安装说明 上传所有文件到服务器 或者宝塔 修改thinkphp伪静态,php版本为7.0 /install 安装 登录后台 /admin 定时任务计划设置 进入宝塔控制面板—–计划任务 填写计划任务 解冻任务 设置时间每小时第2分钟 执行 cd /www/wwwroot/website php think UnfreezeMoney 提…

gulimall-search P125 springboot整合elasticsearch版本冲突

一、问题 spring-boot.version 2.2.4.RELEASE,在gulimall-search pom.xml中添加elasticsearch.version 7.4.2后,发现出现如下问题:elasticsearch版本是springboot引入的6.8.6,没有变为7.4.2。 二、原因 在gulimall-search 的pom文件中&#…

Numpy练习

参考链接 创建数组 TestArray.py import numpy as np# 一维数组 def test1DArray():one np.array([1, 2, 3])print("1D Array:\n", one)# 二维数组 def test2DArray():two np.array([[1, 2, 3], [4, 5, 6]])print("2D Array:\n", two)# 创建全0数组 d…

Python中的列表推导式和字典推导式:优雅且高效的数据结构生成方式

Python中的列表推导式和字典推导式:优雅且高效的数据结构生成方式 在Python中,列表推导式(List Comprehensions)和字典推导式(Dictionary Comprehensions)是两种强大且优雅的工具,它们允许开发…

分享一个简单的文件下载器

抽空写了一个用于下载文件的控制器类,只需要把文件的路径通过参数name传递到后台即可完成文件下载到本地,非常方便~ 控制器类代码 package cn.edu.sgu.www.download.controller;import cn.edu.sgu.www.download.entity.RequestURI; import org.springfr…

Kotlin 中,扩展函数(Extension Functions)

在 Kotlin 中,扩展函数(Extension Functions)是用于向已有的类添加新功能而无需继承或使用装饰模式的一个特性。这允许你通过更自然的语法为现有类型添加方法。 下面是一个简单的扩展函数示例: // 定义一个扩展函数,…

SAP ABAP 三种汇总方法

1.select sum 汇总 select key1 key2 sum ( case zhiduanwhen 1 then suliang1when 2 then suliang2end ) as cnt from table where satue in (1,2) order by key1 key2 "必有 group by key1 key2 "必有2.loop 汇总 在loo…

kettle从入门到精通 第六十四课 ETL之kettle kettle中执行SQL脚本步骤,使用需当心

1、群里有不定时会有同学反馈执行SQL脚本步骤使用有问题,那么咱们今天一起来学习下该步骤。trans中的执行SQL脚本有两方面功能,使用时需小心,不然很容易踩坑。 官方定义: 翻译: 您可以使用此步骤执行 SQL 脚本&#…

安装TTS被卡住不下载应该怎么操作

安装 TTS 模块时,如果发现下载的依赖项数量很多,安装时间过长,并且卡在某些地方,可以尝试以下方法: 1. 确认依赖项的下载是否完成 在安装过程中,检查是否有依赖项已经下载并安装成功。在大多数情况下&…

回溯法——跳房子

跳房子是小朋友玩的游戏。地面上画出一连串格子,每个格子里有一个整数,小朋友从外面跳入格子,并继续往前跳,直到跳出所有格子。每次跳跃的规则是,可以跳入下一格或下下格或下下下格。怎么跳能让落脚格子里的数的累加和…

数据库管理-第198期 升级Oracle ACE Pro,新赛季继续努力(20240605)

数据库管理198期 2024-06-05 数据库管理-第198期 升级ACE Pro,新赛季继续努力(20240605)1 惊喜2 变化3 Oracle ACE总结 数据库管理-第198期 升级ACE Pro,新赛季继续努力(20240605) 作者:胖头鱼的…

区间预测 | Matlab实现QRBiTCN分位数回归双向时间卷积神经网络注意力机制时序区间预测

Matlab实现QRBiTCN分位数回归双向时间卷积神经网络注意力机制时序区间预测 目录 Matlab实现QRBiTCN分位数回归双向时间卷积神经网络注意力机制时序区间预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 Matlab实现QRBiTCN分位数回归双向时间卷积神经网络注意力机制时序…

实现 Python 服务在执行完毕后主动向前端发送信息,以便前端(例如 Vue.js 应用)可以更新显示

可以通过多种方法实现 Python 服务在执行完毕后主动向前端发送信息,以便前端(例如 Vue.js 应用)可以更新显示。下面介绍几种常见的方法: 1. 使用 WebSockets WebSockets 是一种在客户端和服务器之间建立持久连接的通信协议&…

在网页中调用MSTSC打开远程桌面

1.修改注册表 添加自定义URL协议 MSTSC [HKEY_CLASSES_ROOT\MSTSC]"URL:MSTSCProtocol""URL Protocol"""[HKEY_CLASSES_ROOT\MSTSC\DefaultIcon] "mstsc.exe"[HKEY_CLASSES_ROOT\MSTSC\shell][HKEY_CLASSES_ROOT\MSTSC\shell\open][…

C++ STL std::vector的实现机制【面试】

std::vector 是 C 标准模板库(STL)中的一种序列容器,它封装了动态数组的实现,提供了一系列方法来操作这个动态数组。以下是 std::vector 的一些关键实现机制: 连续内存存储: std::vector 通过一块连续的内存…

51单片机在八位数码管上显示自己学号后八位

1、功能描述 在八位数码管上显示自己学号后八位 2、实验原理 数码管就是通过线路将各个LED灯连接在一起。 P2控制LED的段选, P0控制LED位选。读取时从低位向高位读取,P2_2为高位P2_4为地位,例如P2_4 1; P2_3 0; P2_2 1,那么…

LabVIEW飞机发动机测试与故障诊断系统

LabVIEW飞机发动机测试与故障诊断系统 基于LabVIEW开发了一个飞机发动机测试与故障诊断系统,能够实时监测发动机的运行参数,进行数据采集与分析,并提供故障诊断功能。系统采用高精度传感器和数据采集硬件,适用于发动机的性能测试、…

C++ | Leetcode C++题解之第136题只出现一次的数字

题目&#xff1a; 题解&#xff1a; class Solution { public:int singleNumber(vector<int>& nums) {int ret 0;for (auto e: nums) ret ^ e;return ret;} };

MPU6050篇——温度与角度的读取

一、MPU6050的读写时序 1. MPU6050写时序 1. 首先是IIC的起始信号&#xff0c;也就是&#xff1a; MPU_IIC_Start(); 2. 然后接下来便是发送器件地址以及写命令&#xff1a;其中MPU6050的地址为7位&#xff0c;而八位为一个数据帧&#xff0c;所以在最后一位再加一位是指定…

用户管理的小demo--过滤器filter

1、创建 CharEncodingFilter.java package com.by.filter; import javax.servlet.*; import java.io.IOException; public class CharEncodingFilter implements Filter {Overridepublic void init(FilterConfig filterConfig) throws ServletException {}Overridepublic void …