尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Litestar JWT 安全后端实战:JWTAuth、Cookie Auth、OAuth2 密码流与令牌吊销
Litestar JWT 安全后端实战JWTAuth、Cookie Auth、OAuth2 密码流与令牌吊销【免费下载链接】litestarLight, flexible and extensible ASGI framework | Built to scale项目地址: https://gitcode.com/GitHub_Trending/li/litestar本文以 Litestar 官方文档中的 JWT 安全后端章节为主体系统讲解JWTAuth、JWTCookieAuth、OAuth2PasswordBearerAuth三种认证后端的配置与用法并深入 Token 令牌模型、认证中间件 与 配置基类 的源码实现覆盖自定义令牌字段、issuer/audience 校验、载荷解码定制与令牌吊销等全部进阶场景。读完后你可以独立完成一个带 JWT 登录、鉴权、OpenAPI 安全方案注入的完整应用。安装使用 jwt 依赖扩展Litestar 的 JWT 安全后端是可选组件依赖pyjwt和cryptography两个第三方包。最简单的安装方式是启用 Litestar 的jwtextrapip install litestar[jwt]从当前仓库的 pyproject.toml 可以确认该 extra 的具体内容jwt [cryptography, pyjwt2.9.0]即jwt扩展要求pyjwt 2.9.0源码中直接import jwt即 PyJWT 库来编解码令牌。如果不用 extra也可以单独安装这两个包。JWTAuth 后端基于请求头的基础认证JWTAuth是最基础的 JWT 认证后端它从请求头中读取 JWT 令牌认证通过后由你提供的回调把令牌映射为业务用户对象。完整示例见 using_jwt_auth.pyimport secrets from os import environ from typing import Any from uuid import UUID from pydantic import BaseModel, EmailStr from litestar import Litestar, Request, Response, get, post from litestar.connection import ASGIConnection from litestar.openapi.config import OpenAPIConfig from litestar.security.jwt import JWTAuth, Token # 假设我们有一个 User 模型这里用 pydantic也可以是 SQLAlchemy 模型等任意值 class User(BaseModel): id: UUID name: str email: EmailStr MOCK_DB: dict[str, User] {} # JWTAuth 要求一个 retrieve handler 回调接收 Token 与 ASGI 连接返回对应的 User 实例。 # 回调可以是同步或异步函数。 async def retrieve_user_handler(token: Token, connection: ASGIConnection[Any, Any, Any, Any]) - User | None: # 这里是你自己的用户查找逻辑 return MOCK_DB.get(token.sub) jwt_auth JWTAuthUser), # 指定哪些端点跳过认证登录端点和 OpenAPI 文档 exclude[/login, /schema], ) # 基于 JWTAuth 实例创建登录处理器 post(/login) async def login_handler(data: User) - Response[User]: MOCK_DB[str(data.id)] data return jwt_auth.login( identifierstr(data.id), token_extras{email: data.email}, response_bodydata, ) get(/some-path, sync_to_threadFalse) def some_route_handler(request: Request[User, Token, Any]) - Any: # request.user 由中间件设置为 retrieve_user_handler 返回的用户实例 assert isinstance(request.user, User) # request.auth 是由认证头数据构建的 Token 实例 assert isinstance(request.auth, Token) openapi_config OpenAPIConfig(titleMy API, version1.0.0) # 把 jwt_auth.on_app_init 作为初始化钩子传入它会注入 JWT 中间件与 OpenAPI 安全配置 app Litestar( route_handlers[login_handler, some_route_handler], on_app_init[jwt_auth.on_app_init], openapi_configopenapi_config, )核心配置参数源码级说明对照 auth.py 中JWTAuth的 dataclass 定义各参数及其默认值如下参数默认值说明token_secret必填签名密钥。官方建议以环境变量注入不要硬编码retrieve_user_handler必填接收(Token, ASGIConnection)返回用户对象可为任意值同步/异步均可algorithmHS256JWT 签名算法auth_headerAuthorization读取令牌的请求头键也可改为X-Api-Key等default_token_expirationtimedelta(days1)默认令牌过期时间excludeNone跳过认证的 URL 模式单个或列表exclude_opt_keyexclude_from_auth用于在单个路由上禁用认证的检查键exclude_http_methods[OPTIONS, HEAD]无需认证的 HTTP 方法scopesNone中间件处理的 ASGI scopeNone时同时处理 http 与 websocketguardsNone认证之后的授权守卫列表route_handlers/dependenciesNone随配置一起注册的处理器与依赖openapi_security_scheme_nameBearerTokenOpenAPI 安全方案的命名token_clsTokenJWT 载荷转换的目标类型可自定义见下文令牌如何从请求头中被提取从 middleware.py 的JWTAuthenticationMiddleware.authenticate_request可以看到提取逻辑auth_header connection.headers.get(self.auth_header) if not auth_header: raise NotAuthorizedException(No JWT token found in request header) encoded_token auth_header.partition( )[-1]即中间件按空格分割请求头取最后一段作为令牌——这正是Bearer token格式中取token的方式。JWTAuth的login()响应头也是按同一规则生成的format_auth_header会依据 OpenAPI 方案拼出Bearer encoded_token见 auth.py。认证失败与 401在authenticate_tokenmiddleware.py中令牌解码、用户查找、吊销检查三步任一失败都会抛出NotAuthorizedExceptiontoken self.token_cls.decode( encoded_tokenencoded_token, secretself.token_secret, algorithmself.algorithm, audienceself.token_audience, issuerself.token_issuer, require_claimsself.require_claims, verify_expself.verify_expiry, verify_nbfself.verify_not_before, strict_audienceself.strict_audience, ) user await self.retrieve_user_handler(token, connection) token_revoked False if self.revoked_token_handler: token_revoked await self.revoked_token_handler(token, connection) if not user or token_revoked: raise NotAuthorizedException() return AuthenticationResult(useruser, authtoken)成功时返回AuthenticationResult(user..., authtoken)框架将其写入scope[user]和scope[auth]因此处理器内可通过request.user与request.auth访问。JWTCookieAuth 后端HttpOnly Cookie 传递令牌JWTCookieAuth继承自同一套基础配置与JWTAuth的唯一本质区别是令牌放在HttpOnlyCookie 中而不是请求头。示例见 using_jwt_cookie_auth.pyfrom litestar.security.jwt import JWTCookieAuth, Token jwt_cookie_auth JWTCookieAuthUser), exclude[/login, /schema], # 可选的 Cookie 参数例如开启 secure # secureTrue, ) post(/login) async def login_handler(data: User) - Response[User]: MOCK_DB[str(data.id)] data return jwt_cookie_auth.login(identifierstr(data.id), response_bodydata)Cookie 相关的附加参数auth.py参数默认值说明keytokenCookie 名称path/Cookie 有效的路径范围domainNoneCookie 有效域secureNone是否强制 HTTPS 传输samesitelax跨站请求是否携带 Cookie可选lax/strict/none源码中JWTCookieAuth.login()auth.py会构造一个httponlyTrue的Cookie其max_age取自token_expiration或default_token_expiration同时保留响应头中的令牌保证同一登录响应既种 Cookie 又返回认证头。对应的JWTCookieAuthenticationMiddlewaremiddleware.py在提取令牌时优先请求头、回退 Cookieencoded_token ( connection.headers.get(self.auth_header, ).partition( )[-1] or connection.cookies.get(self.auth_cookie_key, ).split( )[-1] ) if not encoded_token: raise NotAuthorizedException(No JWT token found in request header or cookies)OAuth2PasswordBearerAuthOAuth 2.0 密码流OAuth2PasswordBearerAuth面向 OAuth 2.0 Bearer 密码流场景。它在功能上基于 Cookie 认证机制额外要求一个token_url参数指向登录路由并向 OpenAPI 文档注入标准的oauth2密码流安全方案。示例见 using_oauth2_password_bearer.pyfrom litestar.security.jwt import OAuth2Login, OAuth2PasswordBearerAuth, Token oauth2_auth OAuth2PasswordBearerAuthUser), token_url/login, # 获取新令牌的 URL即登录路由 exclude[/login, /schema], ) post(/login) async def login_handler(request: Request[Any, Any, Any], data: User) - Response[OAuth2Login]: MOCK_DB[str(data.id)] data # 不传 response_body 时返回标准 OAuth2 令牌响应 return oauth2_auth.login(identifierstr(data.id)) post(/login_custom) async def login_custom_response_handler(data: User) - Response[User]: MOCK_DB[str(data.id)] data # 也可以自定义响应体 return oauth2_auth.login(identifierstr(data.id), response_bodydata)源码上的差异点auth.pytoken_url: str为必填用于生成 OpenAPIOAuthFlow(token_url..., scopes...)安全方案类型为typeoauth2、flowsOAuthFlows(password...)可选oauth_scopes声明令牌可用的 scopelogin()的send_token_as_response_body默认即为True与JWTAuth不同默认响应体是OAuth2LoginDTOdataclass class OAuth2Login: access_token: str token_type: str refresh_token: str | None None expires_in: int | None None即标准 OAuth2 密码流的{access_token, token_type: bearer, expires_in}响应格式。使用自定义令牌类Token本身是一个 dataclass你可以通过子类化添加任意字段并把子类传给后端的token_cls。最小示例见 custom_token_cls.pyimport dataclasses import secrets from typing import Any from litestar import Litestar, Request, get from litestar.connection import ASGIConnection from litestar.security.jwt import JWTAuth, Token dataclasses.dataclass class CustomToken(Token): token_flag: bool False dataclasses.dataclass class User: id: str async def retrieve_user_handler(token: CustomToken, connection: ASGIConnection) - User: return User(idtoken.sub) TOKEN_SECRET secrets.token_hex() jwt_auth JWTAuthUser get(/, sync_to_threadFalse) def handler(request: Request[User, CustomToken, Any]) - dict[str, Any]: return {id: request.user.id, token_flag: request.auth.token_flag} app Litestar(middleware[jwt_auth.middleware])内置Token的完整字段定义见 token.pyexp过期时间datetime、sub主题必填非空字符串、iat签发时间默认当前 UTC 时间、iss/aud/jti均可选以及extras令牌中出现的其他自定义字段都会自动归入这个 dict。__post_init__会做严格校验sub必须非空、exp必须是未来时间、iat必须是当前或过去时间否则抛出ImproperlyConfiguredException。需要注意的边界官方文档的 important 提示令牌从 JSON 转换到 token 类时只做基础类型转换decode中通过msgspec.convert(payload, cls, strictFalse)完成见 token.py。涉及 Pydantic、attrs 等第三方库的复杂类型转换或自定义type_decoders不可用如需要必须在子类中重写Token.encode与Token.decode方法。验证 issuer 与 audience要校验 JWT 的ississuer与audaudience声明在认证后端上设置accepted_issuers/accepted_audiences列表即可。令牌解码时其 issuer/audience 值会与列表比对任一不匹配即抛出NotAuthorizedException返回401 Unauthorized。示例见 verify_issuer_audience.pyjwt_auth JWTAuthUser, retrieve_user_handlerretrieve_user_handler, accepted_audiences[https://api.testserver.local], accepted_issuers[https://auth.testserver.local], )底层实现链路JWTAuth把accepted_issuers/accepted_audiences透传给中间件的token_issuer/token_audienceauth.py 的middleware属性再由Token.decode组装 PyJWT 的optionsoptions: JWTDecodeOptions { verify_aud: bool(audience), verify_iss: bool(issuer), } if require_claims: options[require] list(require_claims)也就是说只有传了 issuer/audience 才开启对应校验。此外Token.decode还支持require_claims要求令牌必须包含指定声明缺失则 401verify_exp/verify_nbf是否校验exp在未来、nbf在过去后端侧对应verify_expiry/verify_not_before默认均为Truestrict_audience要求aud为单值且精确匹配此模式下accepted_audiences必须是长度为 1 的序列token.py 中有显式检查并抛出ValueError。定制令牌解码重写 decode_payloadToken.decode内部通过类方法decode_payload完成实际的 PyJWT 解码token.py。因此只要子类重写decode_payload就能在拿到原始 payload 字典后做任意预处理再交给父类流程构建 token 实例。示例见 custom_decode_payload.pyimport dataclasses from collections.abc import Sequence from typing import Any from litestar.security.jwt.token import JWTDecodeOptions, Token dataclasses.dataclass class CustomToken(Token): classmethod def decode_payload( cls, encoded_token: str, secret: str | bytes, algorithms: list[str], issuer: str | Sequence[str] | None None, audience: str | Sequence[str] | None None, options: JWTDecodeOptions | None None, ) - Any: payload super().decode_payload( encoded_tokenencoded_token, secretsecret, algorithmsalgorithms, issuerissuer, audienceaudience, optionsoptions, ) # 自定义逻辑把 userexample.com 形式的 sub 截取为域名部分 payload[sub] payload[sub].split(, maxsplit1)[1] return payload调用约定decode_payload由Token.decode以编码后的令牌字符串调用必须返回一个代表解码载荷的 dict随后decode用它构造 token 类实例包括exp/iat的时间戳→datetime 转换、sub必填检查、多余字段归入extras等步骤。令牌吊销Token RevocationJWT 本身无状态无法真正撤销但可以维护一个吊销列表并在认证时校验。框架为此提供了revoked_token_handler参数接收(Token, ASGIConnection)返回True表示该令牌已吊销。完整示例见 using_token_revocation.pyMOCK_DB: dict[str, User] {} BLOCKLIST: dict[str, str] {} async def retrieve_user_handler(token: Token, connection: ASGIConnection[Any, Any, Any, Any]) - User | None: return MOCK_DB.get(token.sub) # 使用吊销功能必须提供 revoked_token_handler async def revoked_token_handler(token: Token, connection: ASGIConnection[Any, Any, Any, Any]) - bool: jti token.jti # 令牌唯一标识JWT ID if jti: revoked BLOCKLIST.get(jti) if revoked: return True return False jwt_auth JWTAuthUser, exclude[/login, /schema], ) post(/login) async def login_handler(data: User) - Response[User]: MOCK_DB[str(data.id)] data # 登录时为每个令牌分配唯一 jti便于精确吊销 return jwt_auth.login( identifierstr(data.id), token_unique_jwt_iduuid4().hex, token_extras{email: data.email}, response_bodydata, ) post(/logout) async def logout_handler(request: Request[User, Token, Any]) - dict[str, str]: jti request.auth.jti if jti: BLOCKLIST[jti] revoked return {message: Token has been revoked.} return {message: No valid token found.}要点登录时用token_unique_jwt_id写入jti——create_token会把该值写入令牌的jti声明auth.py这是按令牌精确吊销的前提登出时把request.auth.jti加入黑名单中间件在用户查找之后执行revoked_token_handler见上文 middleware.py 的源码已吊销的令牌同样返回 401。生产环境黑名单应放在 Redis 等持久化存储中并为其设置与令牌剩余寿命一致的 TTL。挂载方式小结on_app_init 与手动 middleware从 base.py 的AbstractSecurityConfig.on_app_init可以看到把jwt_auth.on_app_init传给Litestar(on_app_init...)时框架自动完成三件事app_config.middleware.insert(0, self.middleware)—— 把 JWT 认证中间件插到中间件栈最内层位置 0若配置了OpenAPIConfig把openapi_components安全方案与security_requirement安全需求注入其中合并guards、dependencies、route_handlers等配置项。如果只需要认证中间件而不需要 OpenAPI 注入也可以像 custom_token_cls.py 那样直接Litestar(middleware[jwt_auth.middleware])jwt_auth.middleware属性返回一个封装了JWTAuthenticationMiddleware的DefineMiddleware所有校验参数issuer、audience、claims、过期等都会透传auth.py。小结Litestar 的 JWT 安全后端把令牌编解码与业务用户映射解耦Token负责声明结构与校验retrieve_user_handler/revoked_token_handler承载业务逻辑JWTAuth/JWTCookieAuth/OAuth2PasswordBearerAuth三种后端分别对应请求头、HttpOnly Cookie、OAuth2 密码流三种传输形态并通过on_app_init一并完成中间件与 OpenAPI 安全方案的注册。相关源码集中在 litestar/security/jwt/auth.py、middleware.py、token.py可运行示例集中在 docs/examples/security/jwt/API 参考见 docs/reference/security/ 下的 JWT 条目。【免费下载链接】litestarLight, flexible and extensible ASGI framework | Built to scale项目地址: https://gitcode.com/GitHub_Trending/li/litestar创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

Arduino IDE跨平台安装与权限配置全解析

Arduino IDE跨平台安装与权限配置全解析

1. 这不是“点下一步就行”的安装,而是嵌入式开发的第一道门槛你搜“Arduino IDE 安装教程”,页面上铺天盖地是截图箭头“双击安装包→点击Next→勾选Add to PATH→Finish”这种流水线操作。我试过用这套流程教三个零基础的大学生——两个卡在驱动没识别…

📅 2026/9/16 14:43:29
JavaWeb仓库管理系统:LayUI+原生Servlet生产级骨架

JavaWeb仓库管理系统:LayUI+原生Servlet生产级骨架

简介:这是一套面向JavaWeb初学者与课程设计者的仓库管理系统实战项目资源,聚焦企业级库存管理场景,覆盖系统分析、设计到部署的完整开发流程。资源包含13个核心功能模块,如登录注册、商品/库存/出入库/订单/报表/权限管理及AI驱动…

📅 2026/9/16 14:43:29
Flame 行为树(Behavior Tree)AI 集成指南:用 flame_behavior_tree 为游戏组件赋予智能决策

Flame 行为树(Behavior Tree)AI 集成指南:用 flame_behavior_tree 为游戏组件赋予智能决策

Flame 行为树(Behavior Tree)AI 集成指南:用 flame_behavior_tree 为游戏组件赋予智能决策 【免费下载链接】flame A Flutter based game engine. 项目地址: https://gitcode.com/GitHub_Trending/fl/flame 本指南围绕 flame_behavior…

📅 2026/9/16 14:43:29
MORE NEWS

更多资讯

📰

SpringBoot整合Nacos常见报错排查与解决方案

1. SpringBoot整合Nacos常见报错场景分类在微服务架构中,SpringBoot与Nacos的整合主要涉及服务注册发现和配置管理两大核心功能。根据实际项目经验,我将典型报错场景分为以下几类:连接类错误:表现为客户端无法与Nacos Server建立连…

📰

Comsol EBG能带计算与伪模式处理技术详解

1. Comsol EBG能带结构计算基础解析电磁带隙结构(EBG)作为一种人工周期性电磁材料,在微波和太赫兹领域具有重要应用价值。使用Comsol Multiphysics进行EBG能带结构计算是研究其电磁特性的有效手段。这种计算方法基于Bloch定理和周期性边界条件…

📰

游戏超分辨率替换:OptiScaler 让你在 DLSS、FSR、XeSS 之间任选,帧率与画质兼得

游戏超分辨率替换:OptiScaler 让你在 DLSS、FSR、XeSS 之间任选,帧率与画质兼得 【免费下载链接】OptiScaler OptiScaler bridges upscaling/frame gen across GPUs. Supports DLSS2/XeSS/FSR2 inputs, replaces native upscalers, enables FSR-FG/XeFG …

📰

多阈值Otsu的MATLAB实现:从类间方差到递归分割实战

简介:这是一份基于OTSU(大津)算法实现的多阈值图像分割MATLAB源码,面向图像处理初学者与需处理复杂场景的算法研究者。资源将经典单阈值分割扩展至多阈值场景,通过灰度直方图统计与类间方差最大化,自动寻找…

📰

Presidio完整指南:免费实现PII检测与数据脱敏,三步跑通敏感信息匿名化

Presidio完整指南:免费实现PII检测与数据脱敏,三步跑通敏感信息匿名化 【免费下载链接】presidio An open-source framework for detecting, redacting, masking, and anonymizing sensitive data (PII) across text, images, and structured data. Supp…

📰

DataHub DataFlow 与 DataJob 实体管理实战:用 Python SDK 构建数据处理管线元数据

DataHub DataFlow 与 DataJob 实体管理实战:用 Python SDK 构建数据处理管线元数据 【免费下载链接】datahub The Context Platform for your Data and AI Stack 项目地址: https://gitcode.com/GitHub_Trending/da/datahub 本篇技术指南围绕 DataHub 中的 D…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬