Next-Auth v5 SSR页面API返回401时自动登出问题求助
Next-Auth v5 SSR页面401自动登出解决方案
针对你在SSR页面遇到的401无法调用signOut的问题,给你几个可行的解决思路:
方法1:服务器端清除会话并重定向
Next-Auth v5的服务器端auth()函数自带登出能力,你可以直接在SSR页面中调用它的signOut方法清除会话,再重定向到登录页完成流程。修改代码如下:
import auth from "@/lib/auth"; import { redirect } from "next/navigation"; export default async function Page() { const session = await auth(); const token = session?.accessToken; const data = await getData({ token: token || "", }); if (data.status === 401) { // 服务器端清除会话 await auth().signOut(); // 重定向到登录页 redirect("/login"); } return ( <>{data.result}</> ); }
auth().signOut()会自动清除会话cookie,重定向后用户就处于未登录状态。
方法2:将401处理逻辑移到客户端组件
如果服务器端重定向不符合需求,可以把数据请求和401检测放到客户端组件中,使用Next-Auth的客户端钩子处理:
先创建客户端组件DataComponent.jsx:
"use client"; import { useSession, signOut } from "next-auth/react"; import { useEffect, useState } from "react"; export default function DataComponent() { const { data: session } = useSession(); const [data, setData] = useState(null); const [error, setError] = useState(null); useEffect(() => { const fetchData = async () => { if (!session?.accessToken) return; const res = await getData({ token: session.accessToken }); if (res.status === 401) { await signOut(); setError(res.error); return; } setData(res.result); }; fetchData(); }, [session]); if (error) return <p>Error: {error}</p>; if (!data) return <p>Loading...</p>; return <>{data}</>; }
然后在SSR页面中引入该组件,同时保留服务器端会话验证:
import auth from "@/lib/auth"; import { redirect } from "next/navigation"; import DataComponent from "./DataComponent"; export default async function Page() { const session = await auth(); if (!session) { redirect("/login"); } return <DataComponent />; }
这种方式既保留了SSR的会话校验能力,又能在客户端触发signOut。
方法3:服务器端标记状态,客户端全局处理
你可以在SSR页面检测到401时设置自定义响应头,然后在根布局的客户端逻辑中监听该头信息,触发登出:
- SSR页面中设置响应头:
import auth from "@/lib/auth"; import { headers } from "next/headers"; export default async function Page() { const session = await auth(); const token = session?.accessToken; const headersList = headers(); const responseHeaders = new Headers(headersList); const data = await getData({ token: token || "", }); if (data.status === 401) { responseHeaders.set("X-Auth-Error", "401"); await auth().signOut(); } return ( <> {data.status === 401 ? <p>Error: {data.error}</p> : <>{data.result}</>} </> ); }
- 在根布局(客户端)中监听并处理:
"use client"; import { signOut } from "next-auth/react"; import { useEffect } from "react"; export default function RootLayout({ children }) { useEffect(() => { fetch(window.location.href, { method: "HEAD" }) .then(res => { if (res.headers.get("X-Auth-Error") === "401") { signOut(); } }); }, []); return ( <html lang="zh-CN"> <body>{children}</body> </html> ); }
这个方案适合需要全局统一处理401登出的场景。
内容的提问来源于stack exchange,提问作者aboyo
相关产品推荐
相关产品推荐

