Next.js13使用next-auth搭建自定义登录门户的路由导入问题求助
Next.js 13 + NextAuth.js 自定义登录门户解决方案
一、解决useRouter导入错误
Next.js 13的App Router(app目录)彻底弃用了next/router,统一改用next/navigation提供的导航API,直接替换导入语句即可:
// 旧写法(仅适用于Pages Router) import { useRouter } from 'next/router' // 新写法(App Router必须用这个) import { useRouter } from 'next/navigation'
如果你的项目还在使用Pages Router(pages目录),可以继续用next/router,但App Router下必须切换到新的导入路径。
二、简化自定义登录/登出实现
1. 先配置NextAuth核心路由
在app/api/auth/[...nextauth]/route.js中完成基础配置,这里以常用的账号密码登录(Credentials提供者)为例:
import NextAuth from 'next-auth' import CredentialsProvider from 'next-auth/providers/credentials' export const authOptions = { providers: [ CredentialsProvider({ name: '账号密码登录', credentials: { email: { label: '邮箱', type: 'email' }, password: { label: '密码', type: 'password' } }, // 这里替换成你的用户校验逻辑(比如查数据库、调用后端接口) async authorize(credentials) { if (!credentials?.email || !credentials?.password) return null // 示例:模拟校验通过,返回用户信息 const user = { id: '1', name: '测试用户', email: credentials.email } return user } }) ], session: { strategy: 'jwt' }, // 指定自定义登录页的路径 pages: { signIn: '/login' } } const handler = NextAuth(authOptions) export { handler as GET, handler as POST }
2. 自定义登录页面(app/login/page.js)
用NextAuth提供的signIn方法快速实现登录逻辑,结合新的useRouter控制跳转:
'use client' import { useState } from 'react' import { signIn } from 'next-auth/react' import { useRouter } from 'next/navigation' export default function LoginPage() { const [email, setEmail] = useState('') const [password, setPassword] = useState('') const router = useRouter() const handleLogin = async (e) => { e.preventDefault() // 调用登录方法,禁用自动跳转以便手动控制 const result = await signIn('credentials', { email, password, redirect: false }) if (result.ok) { router.push('/dashboard') // 登录成功跳转到目标页面 } else { alert(result.error) // 显示登录失败提示 } } return ( <form onSubmit={handleLogin} style={{ maxWidth: '300px', margin: '2rem auto' }}> <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="请输入邮箱" required style={{ display: 'block', width: '100%', margin: '0.5rem 0', padding: '0.5rem' }} /> <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="请输入密码" required style={{ display: 'block', width: '100%', margin: '0.5rem 0', padding: '0.5rem' }} /> <button type="submit" style={{ width: '100%', padding: '0.5rem', cursor: 'pointer' }}> 登录 </button> </form> ) }
3. 自定义登出按钮
用signOut方法实现登出,同样结合useRouter控制跳转:
'use client' import { signOut } from 'next-auth/react' import { useRouter } from 'next/navigation' export default function LogoutButton() { const router = useRouter() const handleLogout = async () => { await signOut({ redirect: false }) router.push('/login') // 登出后跳转到登录页 } return <button onClick={handleLogout} style={{ cursor: 'pointer' }}>登出</button> }
4. 保护路由示例
用useSession判断用户登录状态,未登录则强制跳转:
'use client' import { useSession } from 'next-auth/react' import { useEffect } from 'react' import { useRouter } from 'next/navigation' export default function ProtectedPage() { const { data: session, status } = useSession() const router = useRouter() useEffect(() => { if (status === 'unauthenticated') { router.push('/login') } }, [status, router]) if (status === 'loading') { return <div>加载中...</div> } return <div>欢迎,{session.user.name}!这是仅登录用户可访问的页面</div> }
内容的提问来源于stack exchange,提问作者Bibesh Gurung
相关产品推荐
相关产品推荐

