Starlette SessionMiddleware 将会话数据存储在服务器上还是客户端上?

问题描述 投票:0回答:1

我正在开发一个无状态的 FastAPI 应用程序。身份验证通过 Google OAuth 处理(

openid
电子邮件配置文件范围)。我正在使用
Authlib
,它使用
SessionMiddleware
(
request.session
) 来存储临时代码和状态。现在,我想使用令牌限制对某些端点的访问。为此,我使用从 Google 获得的 id 令牌中的用户电子邮件创建 JWT,将其存储在客户端的 cookie 中,并在每次向受保护端点发出请求时验证它。它正是我想要的。

因为我正在使用

SessionMiddleware
,无论如何我想到了一种不同的方法。我可以将用户电子邮件存储在
SessionMiddleware
的会话中。它会自动创建一个会话 cookie 并将其存储在客户端。为了限制访问,我可以从会话中获取用户。 Starlette 在后台自动验证 cookie。我已经测试过它,它也运行良好,并为我节省了大量 JWT 代码。

我的问题是

SessionMiddleware
是否将会话数据存储在客户端的cookie中,还是只是编码一个ID并将会话数据保存在服务器上?

从我的研究和自己的实施中,我得到了不同的答案。如果我重新启动应用程序,我仍然可以使用令牌访问会话数据。这暗示整个过程是无状态的。如果我检查 Starlette 的源代码,我还认为会话数据直接编码在会话 cookie 中。但我在其他地方都看到人们说

SessionMiddleware
是有状态运行的。

python fastapi stateless starlette
1个回答
0
投票

在默认配置中,

SessionMiddleware
通过直接将会话数据编码到客户端的 cookie 中来存储会话数据。

但如果需要,您可以使用 PyPI 的

aioredis
将会话数据存储在服务器端,并仅在 cookie 中保留 ID(参见 https://pypi.org/project/aioredis/)。

它看起来像这样:

from starlette.middleware.sessions import SessionMiddleware
from fastapi import FastAPI, Request, Depends
import aioredis
import uuid

app = FastAPI()
redis = aioredis.from_url("redis://localhost")

app.add_middleware(SessionMiddleware, secret_key="yoursecretkey")

async def get_session_data(session_id: str):
    session_data = await redis.get(session_id)
    return session_data if session_data else {}

@app.get("/set-session")
async def set_session(request: Request):
    session_id = str(uuid.uuid4())
    await redis.set(session_id, {'your_email': '[email protected]'})
    response = {"message": "Session data set"}
    response.set_cookie(key="session_id", value=session_id)
    return response

@app.get("/get-session")
async def get_session(request: Request):
    session_id = request.cookies.get("session_id")
    session_data = await get_session_data(session_id)
    return {"your_email": session_data.get('your_email')}

希望这有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.