NextAuth登录成功后如何重定向至用户原访问页面?
问题解决:NextAuth登录后重定向回商品页及注册场景处理
一、核心问题:登录后未跳转到callbackUrl的原因
你的登录页(/login)没有正确传递URL中携带的callbackUrl参数给signIn方法,导致NextAuth默认跳转到首页。以下是修复步骤:
1. 修改登录页的表单提交逻辑
确保登录页(客户端组件)从URL查询参数中获取callbackUrl,并在调用signIn时传入该参数:
// app/login/page.js(客户端组件) 'use client' import { useSearchParams } from 'next/navigation' import { signIn } from 'next-auth/react' export default function LoginPage() { const searchParams = useSearchParams() // 获取callbackUrl,默认值设为首页 const callbackUrl = searchParams.get('callbackUrl') || '/' const handleLogin = async (e) => { e.preventDefault() const formData = new FormData(e.target) const email = formData.get('email') const password = formData.get('password') // 调用signIn时传入callbackUrl await signIn('credentials', { email, password, redirect: true, callbackUrl }) } return ( <form onSubmit={handleLogin}> <input type="email" name="email" required /> <input type="password" name="password" required /> <button type="submit">登录</button> </form> ) }
2. 可选:添加Redirect回调增强安全性
在authOptions中添加redirect回调,确保重定向地址是同域名下的合法地址:
export const authOptions = { // ...现有配置 callbacks: { // ...现有jwt、session回调 async redirect({ url, baseUrl }) { // 仅允许同域名或相对路径的重定向 if (url.startsWith(baseUrl)) return url if (url.startsWith('/')) return new URL(url, baseUrl).toString() return baseUrl } }, // ...其余配置 }
二、注册后跳转的场景处理
如果用户从商品页→登录页→注册页,需要将callbackUrl从登录页传递到注册页,注册完成后自动登录并跳转回目标页面:
1. 登录页添加带callbackUrl的注册链接
在登录页中,注册跳转链接携带当前的callbackUrl参数:
// 登录页内的注册链接 <p>还没有账号? <a href={`/register?callbackUrl=${encodeURIComponent(callbackUrl)}`}>立即注册</a> </p>
2. 注册页完成注册后自动登录并跳转
注册页(客户端组件)获取callbackUrl,创建用户后直接调用signIn完成登录并跳转:
// app/register/page.js(客户端组件) 'use client' import { useSearchParams } from 'next/navigation' import { signIn } from 'next-auth/react' import connectDB from '@/lib/db' import Customer from '@/models/Customer' import bcrypt from 'bcrypt' export default function RegisterPage() { const searchParams = useSearchParams() const callbackUrl = searchParams.get('callbackUrl') || '/' const handleRegister = async (e) => { e.preventDefault() const formData = new FormData(e.target) const name = formData.get('name') const email = formData.get('email') const password = formData.get('password') try { await connectDB() // 检查用户是否已存在 const existingUser = await Customer.findOne({ email }) if (existingUser) { alert('该邮箱已注册') return } // 加密密码并创建用户 const hashedPwd = await bcrypt.hash(password, 10) await Customer.create({ name, email, password: hashedPwd, cart: [] }) // 注册成功后自动登录并跳转到目标页面 await signIn('credentials', { email, password, redirect: true, callbackUrl }) } catch (err) { console.error('注册失败:', err) alert('注册出错,请重试') } } return ( <form onSubmit={handleRegister}> <input type="text" name="name" required placeholder="姓名" /> <input type="email" name="email" required placeholder="邮箱" /> <input type="password" name="password" required placeholder="密码" /> <button type="submit">注册</button> </form> ) }
三、验证逻辑检查
你的CredentialsProvider的authorize函数存在一个小问题:当用户不存在时,代码未正确返回值,需修改为:
async authorize(credentials, req) { const { email, password } = credentials try { await connectDB() const customer = await Customer.findOne({ email }) // 修复:用户不存在时返回null if (!customer) return null const pwdComparisonResult = await bcrypt.compare(password, customer.password) if (pwdComparisonResult) { return customer } return null } catch (error) { console.log('error ', error); return null // 捕获错误时也返回null } }
内容的提问来源于stack exchange,提问作者karim
相关产品推荐
相关产品推荐

