Vercel部署后无法重定向至目标页面问题求助
问题描述
访问受保护页面时会被重定向到登录页,原本预期将受保护页面URL存入查询参数,登录后自动跳转回该页面。此逻辑在本地开发环境正常,但部署到Vercel后,登录完成总是跳转到首页/。
相关代码片段:
Middleware 配置
// middleware.ts const { pathname } = request.nextUrl; if (!token && isLoginProtectedPath) { const redirectUrl = pathname; (await cookies()).set('redirect_url', redirectUrl); return NextResponse.redirect(new URL('/auth/login', request.url)); }
登录页逻辑
// login page const searchParams = useSearchParams(); startTransition(async () => { const res = await login(payload); if (res.success) { setIsLogged(true); const redirectUrl = searchParams.get('redirect') || '/'; console.log('login - redirectUrl', redirectUrl); router.push(redirectUrl); return; } toast.error(res.message); });
问题根源
- 参数传递逻辑不匹配:Middleware中将目标页面URL存入了
redirect_urlCookie,但登录页代码却尝试从URL查询参数redirect中取值,两边完全不对应,自然拿不到正确的跳转地址,最终 fallback 到首页。 - 本地环境可能因Cookie读取限制宽松偶然生效,但Vercel部署后,Cookie的跨域/环境适配问题导致无法正确读取,进一步加剧了这个问题。
修复方案
推荐采用URL查询参数传递跳转地址的方式,逻辑更直接且不易出问题:
步骤1:修改Middleware,将跳转地址附加到登录页URL
// middleware.ts const { pathname } = request.nextUrl; if (!token && isLoginProtectedPath) { // 构建登录页URL,并添加redirect查询参数 const loginRedirectUrl = new URL('/auth/login', request.url); loginRedirectUrl.searchParams.set('redirect', pathname); return NextResponse.redirect(loginRedirectUrl); }
步骤2:保持登录页逻辑不变(可选添加校验)
登录页原本从searchParams.get('redirect')取值的逻辑现在可以正常工作。如果需要防止恶意跳转,可添加地址白名单校验:
// login page const searchParams = useSearchParams(); startTransition(async () => { const res = await login(payload); if (res.success) { setIsLogged(true); let redirectUrl = searchParams.get('redirect') || '/'; // 校验跳转地址是否在允许范围内(可选) const allowedPaths = ['/dashboard', '/profile', '/orders']; if (!allowedPaths.includes(redirectUrl) && !redirectUrl.startsWith('/app/')) { redirectUrl = '/'; } router.push(redirectUrl); return; } toast.error(res.message); });
如果坚持使用Cookie传递方式,需修改登录页从Cookie中取值:
// login page(App Router 示例) import { cookies } from 'next/headers'; startTransition(async () => { const res = await login(payload); if (res.success) { setIsLogged(true); // 从Cookie获取跳转地址 const redirectUrl = cookies().get('redirect_url')?.value || '/'; // 清除Cookie避免重复使用 cookies().delete('redirect_url'); router.push(redirectUrl); return; } toast.error(res.message); });
额外注意事项
- 部署到Vercel后,确保
isLoginProtectedPath的路径匹配逻辑正确,避免因生产环境路径差异导致保护规则失效。 - 若使用Cookie传递,需注意Vercel部署环境的Cookie配置(如
domain、path),确保客户端能正确读取。
内容的提问来源于stack exchange,提问作者Mahadi Hasan
相关产品推荐
相关产品推荐

