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

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'],
}

验证步骤

  1. 输入正确账号密码登录,观察控制台是否输出Should redirect now...,确认页面自动跳转
  2. 检查浏览器控制台,确认无Supabase认证相关错误
  3. 确认Supabase后台的站点URL已配置为你的应用域名(避免Cookie跨域问题)

内容的提问来源于stack exchange,提问作者Marib Aldoais

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 16:44:55