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> ) }
验证步骤
- 清除浏览器缓存和Cookie,重启开发服务器
- 未登录状态访问
/todo,确认跳转至/login?callbackUrl=/todo - 登录成功后,确认自动跳转至
/todo - 已登录状态直接访问
/todo,确认能正常进入 - 点击登出,确认跳转至指定的非保护页面(如首页)
内容的提问来源于stack exchange,提问作者Mushroom Terrible
相关产品推荐
相关产品推荐

