Next.js SSR页面安全配置:仅允许已认证用户访问
Next.js SSR页面实现登录用户专属访问方案
由于SSR页面在服务端生成,无法直接读取前端localStorage,核心思路是通过服务端可获取的认证凭证来验证用户身份,以下是两种实用方案:
方案一:基于HTTP Cookie的自定义认证
Cookie会自动随请求头发送到服务端,是SSR场景下传递认证信息的理想方式,推荐使用HttpOnly类型的Cookie提升安全性。
1. 登录时设置认证Cookie
登录接口验证用户身份后,将生成的JWT Token存入HttpOnly Cookie:
// pages/api/login.js(App Router对应app/api/login/route.js) import cookie from 'cookie'; import { generateToken, validateUser } from '../../utils/auth'; export default async function handler(req, res) { if (req.method !== 'POST') return res.status(405).end(); const { username, password } = req.body; const user = await validateUser(username, password); if (user) { const token = generateToken(user); // 设置HttpOnly Cookie,禁止前端直接操作 res.setHeader('Set-Cookie', cookie.serialize('auth_token', token, { httpOnly: true, secure: process.env.NODE_ENV === 'production', // 生产环境启用HTTPS maxAge: 60 * 60 * 24 * 7, // 7天有效期 path: '/', sameSite: 'strict' })); res.status(200).json({ success: true }); } else { res.status(401).json({ success: false, message: '用户名或密码错误' }); } }
2. SSR页面中验证Cookie
在页面的getServerSideProps函数中,从请求头读取Cookie并验证Token有效性,无效则重定向到登录页:
// pages/protected.js(App Router可在page.js中导出getServerSideProps) import cookie from 'cookie'; import { verifyToken } from '../utils/auth'; export async function getServerSideProps(context) { // 解析请求头中的Cookie const cookies = cookie.parse(context.req.headers.cookie || ''); const authToken = cookies.auth_token; // 无Token直接重定向 if (!authToken) { return { redirect: { destination: '/login', permanent: false } }; } try { // 服务端验证Token合法性 const user = await verifyToken(authToken); // 将用户信息传递给页面组件 return { props: { user } }; } catch (err) { // Token无效或过期,重定向登录 return { redirect: { destination: '/login', permanent: false } }; } } export default function ProtectedPage({ user }) { return <div>欢迎登录,{user.username}!这是仅对你开放的SSR页面</div>; }
方案二:使用Auth.js(原NextAuth.js)快速实现
Auth.js是Next.js生态中成熟的认证库,内置支持SSR场景的身份验证,无需手动处理Cookie和Token逻辑。
1. 配置Auth.js认证服务
安装依赖后,创建认证路由:
// app/api/auth/[...nextauth]/route.js import NextAuth from 'next-auth'; import CredentialsProvider from 'next-auth/providers/credentials'; import { validateUser } from '../../../../utils/auth'; const authOptions = { providers: [ CredentialsProvider({ name: '账号密码登录', credentials: { username: { label: '用户名', type: 'text' }, password: { label: '密码', type: 'password' } }, async authorize(credentials) { // 验证用户身份 const user = await validateUser(credentials.username, credentials.password); return user || null; } }) ], session: { strategy: 'jwt' }, // 使用JWT存储会话 secret: process.env.NEXTAUTH_SECRET, // 需在.env中配置密钥 pages: { signIn: '/login' } // 自定义登录页路径 }; const handler = NextAuth(authOptions); export { handler as GET, handler as POST };
2. 保护SSR页面
在页面中通过getServerSession获取会话信息,无会话则重定向:
// app/protected/page.js import { getServerSession } from 'next-auth/next'; import { authOptions } from '../api/auth/[...nextauth]/route'; export async function getServerSideProps(context) { const session = await getServerSession(context.req, context.res, authOptions); if (!session) { return { redirect: { destination: '/login', permanent: false } }; } return { props: { session } }; } export default function ProtectedPage({ session }) { return <div>欢迎,{session.user.username}!这是你的专属SSR页面</div>; }
3. 批量保护路由(可选)
通过Middleware批量指定需要保护的路由,无需在每个页面写验证逻辑:
// middleware.js import { withAuth } from 'next-auth/middleware'; export default withAuth({ pages: { signIn: '/login' } }); // 指定需要保护的路由规则 export const config = { matcher: ['/protected/:path*', '/dashboard'] };
关键注意事项
- 安全性优先:使用
HttpOnlyCookie避免XSS攻击窃取Token;生产环境启用secure属性确保Cookie仅通过HTTPS传输。 - 服务端验证:所有Token验证逻辑必须在服务端完成,禁止依赖前端验证。
- Token过期处理:设置合理的Token过期时间,同时实现刷新Token机制优化用户体验。
内容的提问来源于stack exchange,提问作者Shubham Kumbhare
相关产品推荐
相关产品推荐

