fastapi:用starlette-context实现存储当前登录用户,后续的任何业务代码直接读取,无需通过依赖注入传递

一,安装第三方库

库地址:

https://pypi.org/project/starlette-context/

安装:

$ pip install starlette-context

二,代码

1,登录后把用户信息保存到上下文中

from starlette_context.plugins import Plugin
import jwt

# --- 配置参数 ---
SECRET_KEY = "your-super-secret-key-change-me-1234567890"  # 生产环境请使用安全的随机密钥
ALGORITHM = "HS256"

# 1. Define a custom plugin to extract the Authorization header
class AuthorizationPlugin(Plugin):
    key = "authorization"  # 写到context中时的key
    has_header = True

    async def process_request(self, request):
        # Extract the token from incoming request headers
        auth_header = request.headers.get("Authorization", "")

        dict = {
            "username": '',
            "is_authenticated": False
        }

        if auth_header.startswith("Bearer "):
            token = auth_header[7:]
            print('token:',token)
            # 解密 Token
            payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
            username: str = payload.get("sub")
            print("in plugin username:", username)
            if username:
                # Store user info in context
                dict["username"] = username
                dict["is_authenticated"] = True

        return dict

2, 应用middleware

# app/api/main.py
from fastapi import FastAPI
from starlette.middleware import Middleware

from app.api.middleware.api_sign import SignatureMiddleware
from app.api.middleware.authorization_plugin import AuthorizationPlugin
from app.api.v1 import tasktest, toke, users, account, products,asset
from app.core.exceptions import register_exception_handlers
from fastapi.staticfiles import StaticFiles
from starlette_context import context, plugins
from starlette_context.middleware import ContextMiddleware
from app.api.middleware.auth_middleware import AuthMiddleware
from starlette_context.middleware import ContextMiddleware

# 创建FastAPI应用,并传入 lifespan
api_app = FastAPI(title="我的API项目")

# 注册全局异常捕获
register_exception_handlers(api_app)

# 🚀 注册中间件
api_app.add_middleware(
    ContextMiddleware,
    plugins=(AuthorizationPlugin(),)
)

# 1. 挂载静态文件目录
# path="/static" 是浏览器访问静态文件的 URL 前缀
# directory="app/static" 是本地项目中的文件夹名称
# name="static" 是在 Jinja2 模板中引用时使用的别名
api_app.mount("/static", StaticFiles(directory="app/static"), name="static")

# 注册路由模块
api_app.include_router(account.router)

3, 从函数中获取用户信息: 注意没有传递request

def get_current_user_by_context():
    auth = context.get("authorization")
    print("authorization:", auth)
    if auth is None:
        username = ''
    else:

        is_authenticated = auth["is_authenticated"]
        print("is_authenticated:", is_authenticated)
        if is_authenticated == True:
            username = auth["username"]
        else:
            username = ''
    return {"username": username}

@router.get("/info2")
async def read_users_info2():
    """受保护的路由,只有携带有效 Token 才能访问"""

    user = get_current_user_by_context()

    return {"username": user["username"], "message": "如果username不为空,说明认证成功了!"}

三,测试效果:

image

posted @ 2026-06-29 20:09  刘宏缔的架构森林  阅读(4)  评论(0)    收藏  举报