当前位置: 首页 > news >正文

FastAPI JWT和hash加密

JWT 简介

JWT 即JSON 网络令牌(JSON Web Tokens)。

JWT 是一种将 JSON 对象编码为没有空格,且难以理解的长字符串的标准。JWT 的内容如下所示:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

JWT 字符串没有加密,任何人都能用它恢复原始信息。但 JWT 使用了签名机制。接受令牌时,可以用签名校验令牌。使用 JWT 创建有效期为一周的令牌。第二天,用户持令牌再次访问时,仍为登录状态。

令牌于一周后过期,届时,用户身份验证就会失败。只有再次登录,才能获得新的令牌。如果用户(或第三方)篡改令牌的过期时间,因为签名不匹配会导致身份验证失败。

安装 PyJWT

安装 PyJWT,在 Python 中生成和校验 JWT 令牌:

pip install pyjwt -i https://mirrors.aliyun.com/pypi/simple/

安装这个JWT Python工具包也行 python-jose

在Python中生成和校验JWT令牌,Python-jose 支持PyJWT的所有功能,还支持与其他工具集成时可能会用到的一些其他功能。

pip install python-jose[cryptography] -i https://mirrors.aliyun.com/pypi/simple/

哈希密码

安装 passlib

Passlib 是处理密码哈希的 Python 包。它支持很多安全哈希算法及配套工具。本教程推荐的算法是 Bcrypt。因此,请先安装附带 Bcrypt 的 PassLib:

pip install passlib[bcrypt] -i https://mirrors.aliyun.com/pypi/simple/

解决版本的问题:

pip install passlib --upgrade -i https://mirrors.aliyun.com/pypi/simple/pip install bcrypt==3.2.0 -i https://mirrors.aliyun.com/pypi/simple/ # 一个已知稳定的版本

密码加密验证工具 encrypt_hash.py

from passlib.context import CryptContextclass Encrypt:"""哈希加密"""# 创建用于密码哈希和身份校验的 PassLib 上下文# schemes=["bcrypt"]  bcrypt加密算法# deprecated="auto" 自动选择密码加密方案pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")@classmethoddef get_password_hash(cls, password)-> str:"""获取哈希密码:param password: 明文密码:return:"""return cls.pwd_context.hash(password)@classmethoddef verify_password_hash(cls, password, password_hash) -> bool:"""校验密码:param password: 明文密码:param password_hash: 哈希密码:return:"""return cls.pwd_context.verify(password, password_hash)if __name__ == '__main__':# $2b$12$.gkr.w01NbuufBn5ZZLJnuSmJo6A.CDZ3xLLWgJAkEhsAvfx6kTkm#print(Encrypt.get_password_hash("123"))print(Encrypt.verify_password_hash("123", "$2b$12$.gkr.w01NbuufBn5ZZLJnuSmJo6A.CDZ3xLLWgJAkEhsAvfx6kTkm"))

封装JWT工具

jwt.py文件,生成JWT Token

import time
from typing import Union, Anyfrom jose import jwtclass JWT:"""生成 JWT Token"""# JWT Token令牌有效时长ACCESS_TOKEN_EXPIRE_MINUTES = 30  # 单位:分钟# 加密算法ALGORITHM = "HS256"# 密钥(加密盐)JWT_SECRET_KEY = "98uu7h66te4ss12xbx8zoo9pq77sdf53f0"@classmethoddef create_access_token(cls, subject: Union[str, Any], expires_delta: int = None )-> str:"""根据用户信息创建 JWT Token令牌:param subject: 用户信息,一般为 user_id:param expires_delta: 过期时长 单位: 秒 默认值None:return: token字符串"""# 有效时长if expires_delta:# int(time.time())当前时间,获取整数时间戳(秒级)expires_delta = int(time.time()) + expires_deltaelse:# 系统默认的过期时长 (秒)expires_delta = int(time.time()) + cls.ACCESS_TOKEN_EXPIRE_MINUTES * 60claims = {"exp": expires_delta,"sub": str(subject),}# 生成 JWT Tokenreturn jwt.encode(claims, cls.JWT_SECRET_KEY, algorithm=cls.ALGORITHM)if __name__ == '__main__':print(JWT.create_access_token("0001"))

校验JWT Token的中间件

access_token_middleware.py

import timefrom jose import jwt
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import JSONResponsefrom utils.jwt import JWTclass AccessTokenMiddleware(BaseHTTPMiddleware):"""校验 JWT Token的中间件"""# 不需要访问令牌的URLno_access_token_urls = ["/docs","/user/register","/openapi.json",]async def dispatch(self, request, call_next):# 请求路径path = request.url.path# 如果请求路径需要Token令牌,则进行Token验证if path not in self.no_access_token_urls:# 从Header请求头中获取tokenauthorization = request.headers.get("Authorization")# 如果未获取到Token令牌,则抛出异常if authorization is None:# OAuth2规范,如果认证失败,请求头中返回 "WWW-Authenticate"return no_access_token_response()# 进行Token令牌校验access_token = authorization.split(' ')[1]try:subject: dict = jwt.decode(token=access_token,key=JWT.JWT_SECRET_KEY,algorithms=["HS256"],)# 获取用户IDuser_id = subject.get("sub").split(":")[1]# 缺失用户信息if user_id is None:return lack_user_response()# 判断令牌是否过期expires_delta = subject.get("exp").split(":")[1]if expires_delta is None:return lack_user_response()# 如果令牌过期,则重新登录elif expires_delta <= int(time.time()):return expire_token_response()# 将用户ID存放到Request对象的state中request.state.user_id = user_idexcept Exception as e:print(e)return token_exception_response()# 放行,继续向下执行return await call_next(request)def no_access_token_response():return JSONResponse(status_code=401,content={"code": 111111, "message": "未获取到访问令牌", "data": None},headers={"WWW-Authenticate": "Bearer"},)def lack_user_response():return JSONResponse(status_code=401,content={"code": 222222, "message": "缺失用户信息", "data": None},headers={"WWW-Authenticate": "Bearer"},)def token_exception_response():return JSONResponse(status_code=401,content={"code": 333333, "message": "访问令牌异常", "data": None},headers={"WWW-Authenticate": "Bearer"},)def expire_token_response():return JSONResponse(status_code=401,content={"code": 444444, "message": "令牌过期,请重新登录", "data": None},headers={"WWW-Authenticate": "Bearer"},)

http://www.xdnf.cn/news/715357.html

相关文章:

  • 数据中台系统是什么意思?如何实现数据中台的搭建?
  • MySQL JSON数据存储结构与操作
  • 几款主流V30、V60、V90相机SD卡的评测(索尼、闪迪、三星、雷克沙)
  • ultraiso制作U盘镜像 针对win2012及win2016等需要特殊处理
  • Python训练营打卡 Day39
  • 4 串电池保护芯片创芯微CM1341-DAT使用介绍
  • 板凳-------Mysql cookbook学习 (八--2)
  • [yolov11改进系列]基于yolov11引入倒置残差块块注意力机制iEMA的python源码+训练源码
  • 面向低端设备的移动网页调试策略:WebDebugX 在性能瓶颈分析中的应用
  • 1 µs = 10⁻⁶ s
  • 目标检测预测框置信度(Confidence Score)计算方式
  • ComfyUI+阿里Wan2.1+内网穿透技术:本地AI视频生成系统搭建实战
  • postgresql 流复制中指定同步的用户
  • AI如何让你的智能设备电池更“聪明”?——Python实现智能电池管理
  • 共享内存(SharedArrayBuffer)的使用,以及兼容性情况
  • 【Python零基础入门系列】第5篇:Python 中的函数、模块和文件读写
  • C语言——获取变量所在地址(uint8和uint32的区别)
  • 【Linux网络篇】:初步理解应用层协议以及何为序列化和反序列化
  • Go语言中flag包的用法详解
  • 23、Swift框架微调实战(3)-Qwen2.5-VL-7B LORA微调OCR数据集
  • 计算机视觉---YOLOv4
  • jdk 国内下载镜像站
  • 数据结构 -- 判断正误
  • 微信小程序学习目录
  • 《合同管理系统业务设计》系列三:合同创建与起草流程
  • Cursor系列(1):Cursor安装、虚拟环境
  • 每日算法-250529
  • 【深度学习】13. 图神经网络GCN,Spatial Approach, Spectral Approach
  • 【C语言练习】071. 理解C语言中的信号处理
  • 华为OD机试真题——求最多可以派出多少支队伍(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳实现