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

Next13+AuthJS异常:已登录仍需登录且登录后不跳转

问题诊断与解决方案

核心问题定位

你的问题大概率是AuthJS的session验证逻辑与Next.js 13 App Router路由规则不匹配,或是middleware保护规则、callback配置存在冲突,导致登录状态无法被正确识别,跳转逻辑异常。

分步修复方案

1. 修正middleware.ts的路由匹配规则

Next.js 13 App Router下,middleware的匹配语法有调整,需确保正确指定受保护路由,同时排除AuthJS的回调路径和登录页,避免循环拦截:

// src/middleware.ts
export { default } from "next-auth/middleware"

export const config = {
  matcher: [
    // 保护/todo及其所有子路由
    "/todo/:path*",
    // 排除AuthJS的API路径,避免拦截登录回调
    "!/api/auth/:path*",
    // 排除自定义登录页路径
    "!/login"
  ]
}

2. 调整authOptions的核心配置

优先使用jwt session策略(适配Next13 App Router),同时完善callback逻辑确保跳转和状态同步正常:

// src/app/api/auth/[...nextauth]/route.ts
import NextAuth from "next-auth"
import CredentialsProvider from "next-auth/providers/credentials"

export const authOptions = {
  providers: [
    CredentialsProvider({
      async authorize(credentials) {
        // 这里写你的用户验证逻辑,返回合法用户对象或null
      }
    })
  ],
  session: {
    strategy: "jwt", // App Router下必须用jwt策略,避免session存储异常
    maxAge: 24 * 60 * 60,
  },
  callbacks: {
    async jwt({ token, user }) {
      // 登录时把用户信息写入token
      if (user) {
        token.id = user.id
        token.name = user.name
      }
      return token
    },
    async session({ session, token }) {
      // 把token中的用户信息同步到session,保证前端能获取到登录状态
      session.user = { ...session.user, id: token.id, name: token.name }
      return session
    },
    async redirect({ url, baseUrl }) {
      // 处理登录后的跳转:优先使用合法的callbackUrl
      const callbackUrl = new URL(url).searchParams.get("callbackUrl")
      if (callbackUrl && callbackUrl.startsWith(baseUrl)) {
        return callbackUrl
      }
      // 默认跳转到首页
      return baseUrl
    }
  },
  pages: {
    signIn: "/login", // 指定自定义登录页路径
  }
}

const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }

3. 修复自定义登录页的跳转逻辑

如果使用自定义登录组件,需确保登录时正确传递callbackUrl,并手动控制跳转:

// src/app/login/page.tsx
"use client"

import { signIn } from "next-auth/react"
import { useSearchParams } from "next/navigation"

export default function LoginPage() {
  const searchParams = useSearchParams()
  const callbackUrl = searchParams.get("callbackUrl") || "/"

  const handleLogin = async (e: React.FormEvent) => {
    e.preventDefault()
    // 调用signIn时传入callbackUrl,关闭自动跳转手动控制
    const result = await signIn("credentials", {
      redirect: false,
      username: "你的用户名参数",
      password: "你的密码参数",
      callbackUrl,
    })

    if (!result?.error) {
      // 登录成功后直接跳转到目标页
      window.location.href = callbackUrl
    }
  }

  return (
    <form onSubmit={handleLogin}>
      {/* 你的登录表单元素 */}
    </form>
  )
}

4. 修正登出跳转逻辑

通过signOut的callbackUrl参数指定登出后的跳转路径,避免默认跳转到带保护路由的登录页:

// 示例登出按钮组件
"use client"

import { signOut } from "next-auth/react"

export default function LogoutButton() {
  return (
    <button onClick={() => signOut({ callbackUrl: "/" })}>
      登出
    </button>
  )
}

验证步骤

  1. 清除浏览器缓存和Cookie,重启开发服务器
  2. 未登录状态访问/todo,确认跳转至/login?callbackUrl=/todo
  3. 登录成功后,确认自动跳转至/todo
  4. 已登录状态直接访问/todo,确认能正常进入
  5. 点击登出,确认跳转至指定的非保护页面(如首页)

内容的提问来源于stack exchange,提问作者Mushroom Terrible

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 13:10:15