Next.js中如何访问localStorage数据?React转Next.js开发者求助
解决方案
1. 限制localStorage操作仅在客户端执行
Next.js服务端渲染阶段不存在window对象(localStorage是浏览器API),直接调用会报错。你可以通过两种方式确保代码只在客户端运行:
方式一:使用useEffect钩子
useEffect的回调会在客户端渲染完成后执行,天然避开服务端环境:
import { useEffect } from 'react'; const Login = () => { const handleLogin = async (credentials) => { const res = await fetch('/api/login', { method: 'POST', body: JSON.stringify(credentials), headers: { 'Content-Type': 'application/json' } }); const { token } = await res.json(); // 仅在客户端存储token if (typeof window !== 'undefined') { localStorage.setItem('auth-token', token); } }; // 获取token时同样做客户端判断 useEffect(() => { const token = localStorage.getItem('auth-token'); if (token) { // 执行身份验证后续逻辑 } }, []); return <button onClick={() => handleLogin({ username, password })}>登录</button>; };
方式二:判断window是否存在
在任何可能访问localStorage的代码前,先检查window对象是否存在:
// 存储token if (typeof window !== 'undefined') { localStorage.setItem('auth-token', token); } // 获取token const token = typeof window !== 'undefined' ? localStorage.getItem('auth-token') : null;
2. 改用Cookie存储token(适配SSR场景)
如果需要在服务端渲染时获取用户身份(比如页面初始化时请求用户数据),localStorage无法满足需求,因为服务端无法读取浏览器的localStorage。此时推荐用Cookie存储token:
步骤1:登录接口设置Cookie
在pages/api/login.js中,验证用户后将token写入Cookie(建议设置HttpOnly、Secure属性提升安全性):
export default async function handler(req, res) { if (req.method === 'POST') { const { username, password } = req.body; // 模拟用户验证逻辑 const isValid = username === 'admin' && password === '123456'; if (!isValid) return res.status(401).json({ msg: '验证失败' }); const token = '生成的JWT或自定义token'; // 设置Cookie:HttpOnly防止XSS攻击,Secure仅在HTTPS下传输 res.setHeader('Set-Cookie', `auth-token=${token}; HttpOnly; Secure; Path=/; SameSite=Strict`); res.status(200).json({ success: true }); } }
步骤2:服务端读取Cookie验证
在getServerSideProps中直接从请求对象读取Cookie,完成身份验证后传递数据给页面:
export async function getServerSideProps(context) { const token = context.req.cookies['auth-token']; // 未登录则重定向到登录页 if (!token) { return { redirect: { destination: '/login', permanent: false } }; } // 用token请求用户数据 const userRes = await fetch('https://your-api.com/user', { headers: { Authorization: `Bearer ${token}` } }); const user = await userRes.json(); return { props: { user } }; }
3. 使用NextAuth.js简化身份验证
如果不想手动实现复杂的会话管理,Next.js官方推荐的NextAuth.js可以一站式解决客户端/服务端身份验证问题,支持多种登录方式(账号密码、OAuth等):
步骤1:安装依赖并配置路由
npm install next-auth
创建pages/api/auth/[...nextauth].js:
import NextAuth from 'next-auth'; import CredentialsProvider from 'next-auth/providers/credentials'; export default NextAuth({ providers: [ CredentialsProvider({ async authorize(credentials) { // 调用你的登录接口验证用户 const res = await fetch('/api/login', { method: 'POST', body: JSON.stringify(credentials), headers: { 'Content-Type': 'application/json' } }); const user = await res.json(); if (user) return user; return null; } }) ], session: { strategy: 'jwt' }, // 用JWT存储会话 callbacks: { async jwt({ token, user }) { if (user) token.accessToken = user.token; return token; }, async session({ session, token }) { session.accessToken = token.accessToken; return session; } } });
步骤2:在组件中使用会话
import { useSession, signIn, signOut } from 'next-auth/react'; const Profile = () => { const { data: session } = useSession(); if (!session) return <button onClick={() => signIn()}>登录</button>; return ( <div> <p>欢迎,{session.user.name}</p> <button onClick={() => signOut()}>退出登录</button> </div> ); };
关键注意事项
- 永远不要在服务端渲染的组件顶层(比如函数组件的直接代码块)访问localStorage,必须限制在客户端执行环境中。
- 存储敏感token时,Cookie的
HttpOnly属性比localStorage更安全,能有效防范XSS攻击。 - 使用JWT时,要做好token过期检测和刷新逻辑,避免用户频繁登录。
内容的提问来源于stack exchange,提问作者Nakeeb Raut
相关产品推荐
相关产品推荐

