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

FastAPI+Supabase实现登录/登出/获取用户接口遇None响应求助

问题分析与修复方案

你的接口都返回None主要有三个核心问题:接口无有效返回值、Supabase会话未在请求间保持、错误处理逻辑不当。以下是针对性的修复步骤和完整代码:

核心问题拆解

  • 登录接口:仅用print输出结果,未向客户端返回任何数据;且未处理Supabase登录后的会话存储,导致后续请求无法识别用户。
  • 登出接口:supabase.auth.sign_out()成功时返回None,直接返回该值自然得到None;未清除客户端的会话凭证。
  • 获取用户接口:依赖Supabase SDK的全局会话,但FastAPI是无状态框架,全局会话无法在多请求间保持用户状态,无活跃会话时user()就返回None。

修复后的完整代码

首先确保安装依赖:

pip install fastapi supabase python-multipart uvicorn
from fastapi import FastAPI, Request, Response
from supabase import create_client, Client
import re

# 初始化Supabase客户端
SUPABASE_URL = "你的Supabase项目URL"
SUPABASE_KEY = "你的Supabase服务端密钥"
supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY)

app = FastAPI()

# 邮箱格式校验函数
def check_email(email: str) -> bool:
    pattern = r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
    return re.match(pattern, email) is not None

@app.post('/login')
async def handle_login(user_mail: str, response: Response):
    if not check_email(user_mail):
        return {"status": "error", "message": "邮箱格式不正确"}
    
    try:
        # Supabase邮箱登录(会发送OTP到用户邮箱)
        login_response = supabase.auth.sign_in(email=user_mail)
        if login_response.session:
            # 将会话token存入客户端cookie,用于后续请求身份验证
            response.set_cookie(
                key="access_token",
                value=login_response.session.access_token,
                httponly=True,
                secure=False,  # 生产环境请设为True,本地测试可关闭
                samesite="lax"
            )
            response.set_cookie(
                key="refresh_token",
                value=login_response.session.refresh_token,
                httponly=True,
                secure=False,
                samesite="lax"
            )
            return {"status": "success", "message": "登录请求已发送,请查收邮箱验证码"}
        else:
            return {"status": "error", "message": "登录失败,用户不存在"}
    except Exception as e:
        return {"status": "error", "message": str(e)}

@app.get('/logout')
async def handle_logout(request: Request, response: Response):
    # 从cookie获取refresh_token
    refresh_token = request.cookies.get("refresh_token")
    if refresh_token:
        # 使用refresh_token登出
        error = supabase.auth.sign_out(refresh_token=refresh_token)
        if error:
            return {"status": "error", "message": f"登出失败:{str(error)}"}
    
    # 清除客户端cookie
    response.delete_cookie("access_token")
    response.delete_cookie("refresh_token")
    return {"status": "success", "message": "已成功登出"}

@app.get('/getuser')
async def get_user(request: Request):
    access_token = request.cookies.get("access_token")
    if not access_token:
        return {"status": "error", "message": "未登录,请先登录"}
    
    # 设置当前请求的Supabase auth头部
    supabase.auth.set_auth(access_token)
    user = supabase.auth.user()
    
    if user:
        # 返回脱敏后的用户信息
        return {
            "status": "success",
            "user": {
                "id": user.id,
                "email": user.email,
                "created_at": user.created_at
            }
        }
    else:
        # 若token无效,清除cookie
        response = Response()
        response.delete_cookie("access_token")
        response.delete_cookie("refresh_token")
        return {"status": "error", "message": "登录状态已过期,请重新登录"}

关键修复点说明

  1. 会话持久化:通过FastAPI的Response对象将Supabase的access_token和refresh_token存入客户端httponly cookie,避免前端篡改,同时保证请求间的身份识别。
  2. 接口返回值:所有接口都返回结构化的JSON数据,包含状态标识和消息/数据,不再返回None。
  3. 请求级身份验证:获取用户信息时,从cookie中取出access_token并设置到Supabase客户端,确保每个请求使用当前用户的会话。
  4. 错误处理:增加异常捕获,处理邮箱格式错误、用户不存在、会话过期等场景,返回明确的错误提示。

内容的提问来源于stack exchange,提问作者hassane JABRI

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 23:10:53