You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastApi匿名用户无Cookie会话实现及GetCurrentUser适配咨询

适配FastAPI GetCurrentUser方案实现匿名用户会话数据维护

核心思路是给匿名用户生成临时身份令牌,替代登录用户的访问令牌来标识会话——这完全契合官方GetCurrentUser方案的设计逻辑:用令牌关联用户/会话身份,匿名场景只是把"登录用户令牌"换成"临时会话令牌"。

具体实现步骤&代码示例

1. 基础结构定义

先定义用户模型、会话存储(生产环境建议用Redis替代内存),以及自定义的OAuth2令牌处理类:

from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from pydantic import BaseModel
from uuid import uuid4
from typing import Dict, Optional

# 内存会话存储(生产环境替换为Redis)
session_store: Dict[str, Dict] = {}

# 登录用户模型
class User(BaseModel):
    id: str
    username: str

# 匿名用户模型,标识会话身份
class AnonymousUser(BaseModel):
    id: str
    is_anonymous: bool = True

# 自定义OAuth2依赖:无令牌时自动生成匿名会话令牌
class AnonymousOAuth2Bearer(OAuth2PasswordBearer):
    async def __call__(self, request):
        try:
            # 优先尝试获取登录用户的访问令牌
            token = await super().__call__(request)
            return token
        except HTTPException:
            # 无有效登录令牌时,生成匿名会话令牌并初始化会话数据
            anonymous_token = str(uuid4())
            session_store[anonymous_token] = {"data": {}}
            return anonymous_token

oauth2_scheme = AnonymousOAuth2Bearer(tokenUrl="token")

2. 改造GetCurrentUser依赖

在依赖中统一处理登录用户和匿名会话,返回对应的身份实例:

async def get_current_user(token: str = Depends(oauth2_scheme)):
    # 模拟验证登录用户令牌的逻辑(实际从数据库/缓存校验)
    logged_user = await validate_login_token(token)
    if logged_user:
        return logged_user
    
    # 校验是否为已存在的匿名会话令牌
    if token in session_store:
        return AnonymousUser(id=token)
    
    # 无效令牌时重新生成匿名会话(可选,也可抛出错误)
    new_token = str(uuid4())
    session_store[new_token] = {"data": {}}
    return AnonymousUser(id=new_token)

# 模拟登录令牌验证函数
async def validate_login_token(token: str) -> Optional[User]:
    # 实际业务中根据令牌查询用户,这里返回None模拟无登录用户
    return None

3. 接口中使用会话数据

通过get_current_user依赖获取身份,直接操作对应会话的数据:

app = FastAPI()

# 获取当前会话数据
@app.get("/session-data")
async def get_session_data(current_user: User | AnonymousUser = Depends(get_current_user)):
    if isinstance(current_user, AnonymousUser):
        session_data = session_store[current_user.id]["data"]
        return {"is_anonymous": True, "session_data": session_data}
    return {"is_anonymous": False, "user_info": current_user.dict()}

# 更新会话数据
@app.post("/update-session-data")
async def update_session_data(key: str, value: str, current_user: User | AnonymousUser = Depends(get_current_user)):
    if isinstance(current_user, AnonymousUser):
        session = session_store[current_user.id]
        session["data"][key] = value
        return {"message": "会话数据更新成功", "updated_data": session["data"]}
    return {"message": "登录用户无需维护匿名会话数据"}

关键细节说明

  • 客户端适配:第一次请求无令牌时,服务端会自动生成匿名令牌,需在响应中告知客户端(比如在响应头X-Anonymous-Token返回,或在响应体中携带),后续请求客户端要在Authorization头中带上Bearer <匿名令牌>。
  • 会话过期:生产环境要给会话数据添加过期时间,定时清理无效会话,避免存储资源浪费。
  • 安全性:务必用HTTPS传输令牌,防止匿名会话被劫持。

内容的提问来源于stack exchange,提问作者Henry Thornton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 06:43:18