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": "登录状态已过期,请重新登录"}
关键修复点说明
- 会话持久化:通过FastAPI的
Response对象将Supabase的access_token和refresh_token存入客户端httponlycookie,避免前端篡改,同时保证请求间的身份识别。 - 接口返回值:所有接口都返回结构化的JSON数据,包含状态标识和消息/数据,不再返回
None。 - 请求级身份验证:获取用户信息时,从cookie中取出
access_token并设置到Supabase客户端,确保每个请求使用当前用户的会话。 - 错误处理:增加异常捕获,处理邮箱格式错误、用户不存在、会话过期等场景,返回明确的错误提示。
内容的提问来源于stack exchange,提问作者hassane JABRI
相关产品推荐
相关产品推荐

