NextJS 14 + Supabase认证后重定向失效问题求助
问题:NextJS 14 + Supabase 登录后服务端操作的
redirect不触发重定向 我有一个基于NextJS 14(TypeScript)的应用,使用Supabase作为SaaS后端。登录页面(app/login/page.tsx)渲染登录表单,提交后调用服务端操作signInUser完成认证,确认认证功能正常,但signInUser中的redirect("/")无法触发重定向;仅当手动刷新页面时,middleware才会自动将已认证用户重定向至首页。
核心原因与修复方案
1. redirect被try/catch捕获导致重定向失效
Next.js的redirect()函数通过抛出异常实现重定向逻辑,你的代码将redirect("/")放在try块内,执行时抛出的异常会被catch块捕获,直接中断重定向流程。
修改actions/auth.ts,调整错误处理范围,避免捕获redirect抛出的异常:
"use server" import { revalidatePath } from "next/cache"; import { z } from "zod"; import { createServerClient, type CookieOptions } from '@supabase/ssr' import { cookies } from 'next/headers' import { redirect } from "next/navigation"; export async function signInUser(prevState: any, formData: FormData) { console.log("Action") const schema = z.object({ email: z.string().min(1), password: z.string().min(1) }) try { const signUpFormData = schema.parse({ email: formData.get("email"), password: formData.get("password") }) const cookieStore = cookies() const supabase = createServerClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, { cookies: { get(name: string) { return cookieStore.get(name)?.value }, set(name: string, value: string, options: CookieOptions) { cookieStore.set({ name, value, ...options }) }, remove(name: string, options: CookieOptions) { cookieStore.set({ name, value: '', ...options }) }, }, } ) const { data, error } = await supabase.auth.signInWithPassword({ email: signUpFormData.email, password: signUpFormData.password, }) if (error) { console.log(error) return { message: error.message || "登录失败" } } revalidatePath("/") console.log("Should redirect now...") // redirect抛出的异常不被catch捕获,交给Next.js处理 redirect("/") } catch (e) { // 仅处理Zod验证错误,其他异常(包括redirect)重新抛出 if (e instanceof z.ZodError) { return { message: "表单格式错误" } } throw e } }
2. 优化Middleware会话同步逻辑
调整middleware.ts中的会话获取逻辑,确保会话状态正确同步:
import { createServerClient, type CookieOptions } from '@supabase/ssr' import { NextResponse, type NextRequest } from 'next/server' export async function middleware(request: NextRequest) { console.log("Enter Middleware") let response = NextResponse.next({ request: { headers: request.headers, }, }) const supabase = createServerClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, { cookies: { get(name: string) { return request.cookies.get(name)?.value }, set(name: string, value: string, options: CookieOptions) { request.cookies.set({ name, value, ...options, }) response = NextResponse.next({ request: { headers: request.headers, }, }) response.cookies.set({ name, value, ...options, }) }, remove(name: string, options: CookieOptions) { request.cookies.set({ name, value: '', ...options, }) response = NextResponse.next({ request: { headers: request.headers, }, }) response.cookies.set({ name, value: '', ...options, }) }, }, } ) // 优化会话获取逻辑,直接从session中取user const { data: { session } } = await supabase.auth.getSession() const user = session?.user // 未登录且当前路径非/login时重定向到/login if (!user && !request.nextUrl.pathname.startsWith('/login')) { console.log("redirect to /login") return NextResponse.redirect(new URL('/login', request.url)) } // 已登录且当前路径为/login时重定向到首页 if (user && request.nextUrl.pathname === '/login') { console.log("redirect to /") return NextResponse.redirect(new URL('/', request.url)) } return response } export const config = { matcher: ['/', '/login'], }
验证步骤
- 输入正确账号密码登录,观察控制台是否输出
Should redirect now...,确认页面自动跳转 - 检查浏览器控制台,确认无Supabase认证相关错误
- 确认Supabase后台的站点URL已配置为你的应用域名(避免Cookie跨域问题)
内容的提问来源于stack exchange,提问作者Marib Aldoais
相关产品推荐
相关产品推荐

