JWT令牌如何在FastAPI中实现安全又高效的生成与验证?
title: JWT令牌如何在FastAPI中实现安全又高效的生成与验证?
date: 2025/06/10 09:02:35
updated: 2025/06/10 09:02:35
author: cmdragon
excerpt:
JWT(JSON Web Token)是一种用于安全传递声明信息的开放标准,由头部、载荷和签名三部分组成。在FastAPI中,JWT常用于用户身份认证、API授权和跨服务通信。通过python-jose
库生成和验证JWT,核心步骤包括配置安全参数、生成访问令牌、实现登录接口和验证机制。令牌生成时需设置过期时间以防止长期盗用,验证时通过中间件检查令牌的有效性。此外,可通过刷新令牌机制更新访问令牌,确保系统的安全性和用户体验。
categories:
- 后端开发
- FastAPI
tags:
- JWT
- FastAPI
- 令牌生成
- 令牌验证
- 身份认证
- 安全通信
- 无状态会话


扫描二维码
关注或者微信搜一搜:编程智域 前端至全栈交流与成长
探索数千个预构建的 AI 应用,开启你的下一个伟大创意:https://tools.cmdragon.cn/
第四章:JWT 令牌的生成与验证机制
1. JWT 基础概念
JSON Web Token(JWT)是一种开放标准(RFC 7519),用于在双方之间安全地传递声明信息。它由三部分组成:
- Header(头部):描述算法和令牌类型
- Payload(载荷):携带用户数据(如用户ID)和声明(如过期时间)
- Signature(签名):用于验证令牌完整性的加密字符串
JWT 在 FastAPI 中的典型应用场景:
- 用户身份认证
- API 接口授权
- 跨服务的安全通信
- 无状态会话管理
2. 环境准备
安装所需依赖库(推荐使用虚拟环境):
pip install fastapi==0.95.2 python-jose[cryptography]==3.3.0 passlib==1.7.4 bcrypt==4.0.1 uvicorn==0.22.0
3. 生成 JWT 令牌
3.1 核心配置类
from datetime import datetime, timedelta
from jose import JWTError, jwt
from passlib.context import CryptContext
from pydantic import BaseModel
# 安全配置
SECRET_KEY = "your-secret-key-here" # 生产环境应从环境变量获取
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
# 密码哈希配置
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
class Token(BaseModel):
access_token: str
token_type: str
class TokenData(BaseModel):
username: str | None = None
3.2 令牌生成函数
def create_access_token(data: dict, expires_delta: timedelta | None = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=15)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
3.3 登录接口实现
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm
router = APIRouter()
@router.post("/token", response_model=Token)
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
user = authenticate_user(fake_users_db, form_data.username, form_data.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Bearer"},
)
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={"sub": user.username}, expires_delta=access_token_expires
)
return {"access_token": access_token, "token_type": "bearer"}
4. JWT 验证机制
4.1 令牌验证中间件
from fastapi.security import OAuth2PasswordBearer
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
async def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
token_data = TokenData(username=username)
except JWTError:
raise credentials_exception
user = get_user(fake_users_db, username=token_data.username)
if user is None:
raise credentials_exception
return user
4.2 受保护路由示例
@router.get("/users/me/")
async def read_users_me(current_user: User = Depends(get_current_user)):
return current_user
5. 令牌刷新机制
实现令牌刷新接口:
@router.post("/refresh")
async def refresh_token(refresh_token: str):
try:
payload = jwt.decode(refresh_token, SECRET_KEY, algorithms=[ALGORITHM])
username = payload.get("sub")
if username is None:
raise HTTPException(status_code=400, detail="Invalid token")
# 检查用户是否存在(需要实现具体数据库查询)
user = get_user(username)
if not user:
raise HTTPException(status_code=404, detail="User not found")
new_token = create_access_token(data={"sub": user.username})
return {"access_token": new_token}
except JWTError:
raise HTTPException(status_code=401, detail="Invalid token")
课后Quiz
为什么JWT需要设置过期时间?
A) 减少服务器内存占用
B) 防止令牌被长期盗用
C) 提高加密强度
D) 简化开发流程以下哪个做法会破坏JWT的安全性?
A) 使用HTTPS传输令牌
B) 将敏感数据存储在Payload中
C) 定期轮换加密密钥
D) 验证签名算法如何处理令牌过期的情况?
A) 返回500错误
B) 要求用户重新登录
C) 使用refresh token获取新令牌
D) 自动延长过期时间
答案:
- B - 设置过期时间可限制令牌有效期,降低被盗用后的风险
- B - Payload内容虽然被加密但可被解码,不应存储敏感信息
- C - 最佳实践是通过refresh token机制更新访问令牌
常见报错解决方案
401 Unauthorized: Could not validate credentials
- 原因:无效的令牌格式或签名不匹配
- 解决:检查请求头的Bearer token格式,验证密钥一致性
422 Validation Error
- 原因:请求体与Pydantic模型不匹配
- 预防:使用精确的模型定义,添加字段验证规则
500 Internal Server Error: JWTError
- 原因:令牌解码失败或算法不匹配
- 处理:捕获JWTError异常,返回401状态码
- 检查:确保服务端使用的算法与生成令牌时一致
AttributeError: 'NoneType' has no attribute 'username'
- 原因:数据库查询返回空值
- 修复:在数据库查询后添加空值检查
- 优化:使用Optional类型注解和空值处理
最佳实践建议:
- 生产环境使用RSA非对称加密(RS256算法)
- 将密钥存储在环境变量或密钥管理服务中
- 设置合理的令牌有效期(通常访问令牌15分钟,刷新令牌7天)
- 实现令牌撤销清单(黑名单机制)
余下文章内容请点击跳转至 个人博客页面 或者 扫码关注或者微信搜一搜:编程智域 前端至全栈交流与成长
,阅读完整的文章:JWT令牌如何在FastAPI中实现安全又高效的生成与验证? | cmdragon's Blog
往期文章归档:
- 你的密码存储方式是否在向黑客招手? | cmdragon's Blog
- 如何在FastAPI中轻松实现OAuth2认证并保护你的API? | cmdragon's Blog
- FastAPI安全机制:从OAuth2到JWT的魔法通关秘籍 | cmdragon's Blog
- FastAPI认证系统:从零到令牌大师的奇幻之旅 | cmdragon's Blog
- FastAPI安全异常处理:从401到422的奇妙冒险 | cmdragon's Blog
- FastAPI权限迷宫:RBAC与多层级依赖的魔法通关秘籍 | cmdragon's Blog
- JWT令牌:从身份证到代码防伪的奇妙之旅 | cmdragon's Blog
- FastAPI安全认证:从密码到令牌的魔法之旅 | cmdragon's Blog
- 密码哈希:Bcrypt的魔法与盐值的秘密 | cmdragon's Blog
- 用户认证的魔法配方:从模型设计到密码安全的奇幻之旅 | cmdragon's Blog
- FastAPI安全门神:OAuth2PasswordBearer的奇妙冒险 | cmdragon's Blog
- OAuth2密码模式:信任的甜蜜陷阱与安全指南 | cmdragon's Blog
- API安全大揭秘:认证与授权的双面舞会 | cmdragon's Blog
- 异步日志监控:FastAPI与MongoDB的高效整合之道 | cmdragon's Blog
- FastAPI与MongoDB分片集群:异步数据路由与聚合优化 | cmdragon's Blog
- FastAPI与MongoDB Change Stream的实时数据交响曲 | cmdragon's Blog
- 地理空间索引:解锁日志分析中的位置智慧 | cmdragon's Blog
- 异步之舞:FastAPI与MongoDB的极致性能优化之旅 | cmdragon's Blog
- 异步日志分析:MongoDB与FastAPI的高效存储揭秘 | cmdragon's Blog
- MongoDB索引优化的艺术:从基础原理到性能调优实战 | cmdragon's Blog
- 解锁FastAPI与MongoDB聚合管道的性能奥秘 | cmdragon's Blog
- 异步之舞:Motor驱动与MongoDB的CRUD交响曲 | cmdragon's Blog
- 异步之舞:FastAPI与MongoDB的深度协奏 | cmdragon's Blog
- 数据库迁移的艺术:FastAPI生产环境中的灰度发布与回滚策略 | cmdragon's Blog
- 数据库迁移的艺术:团队协作中的冲突预防与解决之道 | cmdragon's Blog
- 驾驭FastAPI多数据库:从读写分离到跨库事务的艺术 | cmdragon's Blog
- 数据库事务隔离与Alembic数据恢复的实战艺术 | cmdragon's Blog
- FastAPI与Alembic:数据库迁移的隐秘艺术 | cmdragon's Blog
- 飞行中的引擎更换:生产环境数据库迁移的艺术与科学 | cmdragon's Blog
- Alembic迁移脚本冲突的智能检测与优雅合并之道 | cmdragon's Blog
- 多数据库迁移的艺术:Alembic在复杂环境中的精妙应用 | cmdragon's Blog
- 数据库事务回滚:FastAPI中的存档与读档大法 | cmdragon's Blog
- Alembic迁移脚本:让数据库变身时间旅行者 | cmdragon's Blog
- 数据库连接池:从银行柜台到代码世界的奇妙旅程 | cmdragon's Blog
- 点赞背后的技术大冒险:分布式事务与SAGA模式 | cmdragon's Blog
- XML Sitemap
JWT令牌如何在FastAPI中实现安全又高效的生成与验证?的更多相关文章
- 如何在IJ中使用Jaxb2通过xml定义生成对应的Java Entity类的文件
#0. 准备要转换的xml文件,在Project视界中,右击这个xml文件,在弹出的菜单上选择“Generate XSD schema from XML File...”, 按默认设置生成xsd文件. ...
- 如何在SpringBoot中集成JWT(JSON Web Token)鉴权
这篇博客主要是简单介绍了一下什么是JWT,以及如何在Spring Boot项目中使用JWT(JSON Web Token). 1.关于JWT 1.1 什么是JWT 老生常谈的开头,我们要用这样一种工具 ...
- spring security oauth2搭建resource-server demo及token改造成JWT令牌
我们在上文讲了如何在spring security的环境中搭建基于oauth2协议的认证中心demo:https://www.cnblogs.com/process-h/p/15688971.html ...
- Spring Boot Security OAuth2 实现支持JWT令牌的授权服务器
概要 之前的两篇文章,讲述了Spring Security 结合 OAuth2 .JWT 的使用,这一节要求对 OAuth2.JWT 有了解,若不清楚,先移步到下面两篇提前了解下. Spring Bo ...
- 第39章 引用令牌 - Identity Server 4 中文文档(v1.0.0)
访问令牌有两种形式 - 自包含或引用. JWT令牌将是一个自包含的访问令牌 - 它是一个带有声明和过期的受保护数据结构.一旦API了解了密钥材料,它就可以验证自包含的令牌,而无需与发行者进行通信.这使 ...
- 阶段5 3.微服务项目【学成在线】_day18 用户授权_03-方法授权-jwt令牌包含权限
修改认证服务的UserDetailServiceImpl类,下边的代码中 permissionList列表中存放了用户的权限, 并且将权限标识按照中间使用逗号分隔的语法组成一个字符串,最终提供给Spr ...
- 什么是JWT令牌认证?
当下,JWT(JSON Web Token)令牌认证已经变得越来越流行.本文主要介绍JWT令牌认证与传统的Session会话认证机制的区别. 为什么需要认证? HTTP是一种无状态协议,那就意味着当前 ...
- OAuth + Security - 3 - JWT令牌
为什么使用JWT令牌 在上面的资源服务器中,通过配置,我们了解到,当我们拿着token去获取资源时,程序会先去调用远程认证服务器的端点去验证解析token,或者在本地解析校验token,这样毫无疑问, ...
- 畅购商城(八):微服务网关和JWT令牌
好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 畅购商城(一):环境搭建 畅购商 ...
- Jwt令牌创建
添加依赖 <dependencies> <!-- jwt --> <dependency> <groupId>io.jsonwebtoken</g ...
随机推荐
- C#语言碎片:Switch-Case语句字符串匹配
Switch case语句在处理字符串类型匹配时候,case条件需要设置为静态常量或者一个具体的字符串: 因为工具类ToolHand.Name 为变量,所以编译不通过. 使用if语句来逐个判断: 看A ...
- mysql [ERR] 1273 - Unknown collation: 'utf8mb4_0900_ai_ci'
这是因为当前数据库版本较高,需要更改一些参数 解决方法: 将sql文件中的 utf8mb4_0900_ai_ci替换为utf8_general_ci utf8mb4替换为utf8 再次运行SQL文件即 ...
- delphi 让执行程序不在任务栏显示
Application.MainFormOnTaskbar := False; procedure TForm1.FormShow(Sender: TObject); begin ShowWindow ...
- dxTabbedMDIManager1关闭窗体
procedure TfrmJianKongXinXi.FormClose(Sender: TObject; var Action: TCloseAction);begin Action:=caFre ...
- 【SpringCloud】SpringCloud Alibaba Sentinel实现熔断与限流
SpringCloud Alibaba Sentinel实现熔断与限流 限流与降级 限流 blockHandler 降级 fallback 降级需要运行时出现异常才会触发,而限流一旦触发,你连运行的机 ...
- This APT has Super Cow Powers.
在Debian/Ubuntu上,apt包管理器内嵌着一个彩蛋. 如果你在命令行界面输入 apt help 在最后一行能找到This APT has Super Cow Powers. 说明该apt具有 ...
- 调用 restful的api的方法
var // myurl : string; tmpstr : String;// string; RespData :TStringStream; sendData : TStringList; j ...
- Python 类型检查与类型注解:mypy 与 typing 深度解析
Python 类型检查与类型注解:mypy 与 typing 深度解析 在 Python 动态类型语言中,mypy 和 typing 是两个提升代码健壮性的核心工具.它们通过静态类型检查与类型注解,帮 ...
- Kylin-Server-V10-SP3物理机安装简要过程
1.下载镜像 链接: https://eco.kylinos.cn/partners/mirror.html?class_id=1&query_key=V10 选择: 银河麒麟高级服务器操作系 ...
- CAS前后端分离解决方案
CAS前后端分离解决方案 关于CSS服务器的搭建和整合SpringBoot参考:CAS5.3服务器搭建与客户端整合SpringBoot以及踩坑笔记 环境与需求 后端:springboot 前端: vu ...