如何在tRPC上下文中获取Supabase Auth用户会话数据?
在T3栈的tRPC上下文中获取Supabase Auth会话的正确方法
核心思路
在tRPC的createTRPCContext中,使用Supabase官方的createServerSupabaseClient创建服务器端客户端是标准且合理的做法——因为每个请求的req/res对象不同,需要绑定当前请求上下文来正确处理cookie中的会话信息,并非重复创建冗余实例。
步骤1:在createTRPCContext中获取会话
在你的tRPC上下文定义文件(通常是src/server/api/trpc.ts)中,编写如下代码:
import { createServerSupabaseClient } from '@supabase/auth-helpers-nextjs'; import { type CreateNextContextOptions } from '@trpc/server/adapters/next'; import { prisma } from '../db'; // 导入你的Prisma客户端 export const createTRPCContext = async (opts: CreateNextContextOptions) => { const { req, res } = opts; // 创建绑定当前请求的Supabase服务器端客户端 const supabase = createServerSupabaseClient({ req, res }); // 获取当前会话 const { data: { session } } = await supabase.auth.getSession(); return { supabase, session, prisma, // 把Prisma也传入上下文,方便路由使用 }; };
步骤2:封装认证中间件(可选但推荐)
创建一个中间件来检查会话是否存在,简化受保护路由的编写:
import { initTRPC, TRPCError } from '@trpc/server'; import { type Context } from './context'; // 导入你定义的上下文类型 const t = initTRPC.context<Context>().create(); // 检查用户是否已认证的中间件 const isAuthed = t.middleware(({ ctx, next }) => { if (!ctx.session?.user) { throw new TRPCError({ code: 'UNAUTHORIZED' }); } return next({ ctx: { // 细化会话用户的类型,避免后续类型断言 session: { ...ctx.session, user: ctx.session.user }, }, }); }); // 导出公开和受保护的Procedure export const publicProcedure = t.procedure; export const protectedProcedure = t.procedure.use(isAuthed); export const router = t.router;
步骤3:在tRPC路由中使用会话
现在可以在路由中直接通过上下文获取会话,比如:
import { router, publicProcedure, protectedProcedure } from '../trpc'; export const appRouter = router({ // 公开路由:无需认证即可访问 getPublicData: publicProcedure.query(() => { return { message: '这是公开内容' }; }), // 受保护路由:仅登录用户可访问 getUserProfile: protectedProcedure.query(async ({ ctx }) => { // 直接从上下文获取已认证的用户信息 const userProfile = await ctx.prisma.user.findUnique({ where: { id: ctx.session.user.id }, }); return userProfile; }), }); export type AppRouter = typeof appRouter;
关键说明
createServerSupabaseClient内部会自动处理请求中的cookie,确保会话数据与当前请求绑定,每次请求创建是符合Next.js服务器端逻辑的,不存在冗余问题。- 若你担心性能,Supabase的服务器端客户端本身是轻量的,不会带来额外负担。
内容的提问来源于stack exchange,提问作者crevulus
相关产品推荐
相关产品推荐

