
文章目录1. 登录成功后token/session 的生成和存储1.1 生成过程1.2 存放位置1.3 有效期2. 为什么 NextAuth 的 token 存在 Cookie而不是 localStorage/sessionStorage2.1 原因2.2 可以改吗3. 每次调用业务接口时都会携带 NextAuth 的 token 吗4. NextAuth 的 token 和日常的 JWT token不是重复了吗4.1 区别4.2 为什么看起来重复 总结5 NextAuth session 过期maxAge后怎么办怎么重新认证5.1 机制5.2 过期后怎么办6 浏览器上的 Cookie为什么有好几个6.1 next-auth.session-token6.2 next-auth.csrf-token6.3 next-auth.callback-url7 NextAuth Session 过期处理方案7.1 客户端检测useSession Hook7.2 服务端检测getServerSession7.3 API 接口保护7.4 用户体验优化自动续期书接上文NextAuth 认证实战提示这篇文章主要是记录在Next.js中使用NextAuth认证中常见的问题利于对NextAuth的深刻理解。这几个其实都是很多人第一次用NextAuth.js会困惑的点。1. 登录成功后token/session 的生成和存储登录成功后token 是通过NextAuth的signIn方法生成的默认会将 token 存放在cookie中时间是30天(可配置)。NextAuth的工作流程和JWT有点不一样默认是基于 Cookie/Session。1.1 生成过程用户在/api/auth/[...nextauth]用CredentialsProvider登录成功后NextAuth 会生成一个Session 对象{user:{id:1,name:Alice,email:aliceexample.com},expires:2025-09-26T09:00:00.000Z}同时它会在浏览器 Cookie中存储一个加密的 session token名字是next-auth.session-token生产环境 HTTPS 下__Secure-next-auth.session-token安全模式下1.2 存放位置不是localStorage或sessionStorage而是浏览器 Cookie。你可以在浏览器 → 开发者工具 → 应用 (Application) → Cookie → 找到。如图1.3 有效期默认30 天并且每次请求会刷新过期时间。你可以在authOptions.session里配置session:{strategy:jwt,// 或 databasemaxAge:60*60*24*7,// 7天updateAge:60*60*24,// 每24小时刷新一次},maxAge: session 过期时间秒数updateAge: 访问后多久刷新 Cookie 里的过期时间2. 为什么 NextAuth 的 token 存在 Cookie而不是 localStorage/sessionStorage2.1 原因安全性Cookie 可以设置为HttpOnly这样前端 JS 读不到防止XSS 窃取 token。而如果放在localStorage或sessionStorage只要页面有个 XSS 漏洞攻击者就能直接拿到 token。自动携带Cookie 是浏览器在请求同源接口时自动附带的不需要你手动在fetch或axios里加Authorizationheader。这样就能保证前后端天然对接不用每个请求都写 token 注入逻辑。跨子域支持设置 Cookie 的domain.example.com后api.example.com和app.example.com都能共享登录状态。localStorage只能在同一个域名下共享。2.2 可以改吗理论上可以让NextAuth使用jwt模式然后你手动存到localStorage但是不推荐安全性大幅降低容易被 XSS 攻击。NextAuth的设计初衷就是默认用 Cookie 来维护会话 (session)尽量减少开发者手工处理。3. 每次调用业务接口时都会携带 NextAuth 的 token 吗✅是的—— 只要是同源请求比如/api/xxx浏览器会自动在请求头里带上Cookie: next-auth.session-tokenxxxx 这就是为什么在/api/protected/route.ts里你只需要写constsessionawaitgetServerSession(authOptions);就能直接拿到用户信息因为 NextAuth 会解密 Cookie找到对应的 session。如果你用的是跨域比如前端在http://localhost:3000API 在http://localhost:4000那就要设置credentials: includefetch/axios后端允许Access-Control-Allow-Credentials: true4. NextAuth 的 token 和日常的 JWT token不是重复了吗这是一个关键点很多人第一次接触会误会。4.1 区别传统 JWT 鉴权自己实现时登录成功 → 后端返回一个 JWT → 前端存localStorage或 Cookie。前端每次请求时 → 手动在Authorization: Bearer xxx里带上 JWT。后端校验 JWT → 放行。NextAuth 的 session token登录成功 → NextAuth 自动生成一个加密的 session token放在 Cookie。前端请求时 → 浏览器自动带 Cookie。NextAuth 校验 Cookie → 获取 session。4.2 为什么看起来重复如果你只是「前端 自己写的后端 API」那么确实用 JWT 就够了不需要再套一层。但 NextAuth 的目标是开箱即用少写逻辑。支持多种登录方式GitHub / Google / Credentials / Email Link / SSO。不用每个地方都手动写 JWT 校验。你可以理解为JWT自己写的「低层 API」灵活但要维护。NextAuth一个「高层封装」里面也可能用到 JWT但主要靠 Cookie 来维护登录态。 总结为什么存 Cookie更安全 (HttpOnly)自动携带不用手动加 token支持跨子域共享请求接口时浏览器自动带上next-auth.session-token同源请求跨域需要credentials: include和 JWT 的关系不是重复而是两种思路JWT → 你自己维护 token。NextAuth → 代替你管理 session用 Cookie 保持状态。如果你的项目只需要前后端分离 JWT可以不用 NextAuth。如果你需要快速接入多种认证方式或者不想维护 JWT 刷新逻辑用 NextAuth 更方便。5 NextAuth session 过期maxAge后怎么办怎么重新认证5.1 机制在authOptions.session里你可以设置session:{strategy:jwt,// 或 databasemaxAge:60*60*24,// 一天秒updateAge:60*60*24,// 每24小时刷新一次 Cookie}maxAgesession 最长有效时间比如 1 天。updateAge用户只要有访问比如打开页面、调用 APINextAuth 就会自动刷新 Cookie 的过期时间延长有效期。 这意味着如果用户每天至少访问一次登录状态会一直保持。如果用户一天都没访问session 就会过期。5.2 过期后怎么办如果 session 过期NextAuth 的getServerSession会返回null。这时你要做的就是页面redirect(/auth/signin)跳转登录页。API返回401 Unauthorized前端捕获后跳转登录页。换句话说过期后就是重新登录NextAuth 不会像 OAuth 那样自动刷新 token除非你用的是 Google/GitHub provider这种情况下会内置 refresh 逻辑。如果你希望 “自动续期”可以设置maxAge大一点比如7 天或30 天。配合updateAge只要用户活跃就一直续命。总结session 过期怎么办maxAge控制最大有效期updateAge控制刷新机制。用户活跃 → 自动续命长时间不访问 → session 过期必须重新登录。6 浏览器上的 Cookie为什么有好几个NextAuth会生成多个 Cookie每个负责不同功能。常见的有6.1 next-auth.session-token这是最重要的登录态 Cookie。存储加密的 session 信息后端用它识别用户。过期时间 session.maxAge。设置了HttpOnly和Secure生产环境下JS 不能读。6.2 next-auth.csrf-token用于防止CSRF 攻击跨站请求伪造。主要在登录表单提交时用。存在于浏览器 Cookie但前端提交时 NextAuth 会对比校验。这个 cookie 本身安全性要求没那么高但仍然有过期时间一般是 1 天。6.3 next-auth.callback-url用来保存登录后的回跳地址。比如你访问/dashboard被重定向到/auth/signin登录成功后会自动回到/dashboard。这个 cookie 就是存储你原来想去的页面 URL。临时性 cookie登录完成后基本就没用了。总结next-auth.session-token→ 维持登录态next-auth.csrf-token→ 防止 CSRF 攻击next-auth.callback-url→ 保存回跳地址登录成功后重定向7 NextAuth Session 过期处理方案下面是一份NextAuth.js Session 过期后自动检测 重定向登录的完整方案包含前端客户端检测和服务端页面保护两种方式。7.1 客户端检测useSession Hook在前端组件里可以用next-auth/react提供的useSession()它会返回status: authenticated | unauthenticated | loadingdata: session | null示例高阶组件保护页面 .tsxuse client;import{useSession}fromnext-auth/react;import{useRouter}fromnext/navigation;import{useEffect}fromreact;exportdefaultfunctionProtectedClient({children}:{children:React.ReactNode}){const{data:session,status}useSession();constrouteruseRouter();useEffect((){if(statusunauthenticated){router.push(/auth/signin);// 未登录 → 跳转登录}},[status,router]);if(statusloading){returnpLoading.../p;// 页面加载中}if(statusauthenticated){return{children}/;// 已登录 → 渲染内容}returnnull;} 使用时直接包裹页面内容importProtectedClientfrom/components/ProtectedClient;exportdefaultfunctionDashboardPage(){return(ProtectedClienth1Dashboard/h1/ProtectedClient);}7.2 服务端检测getServerSessionApp Router下推荐在page.tsx里用getServerSession()这样用户直接请求时就能被拦截。示例保护 Dashboard 页面import{getServerSession}fromnext-auth;import{authOptions}from../api/auth/[...nextauth]/route;import{redirect}fromnext/navigation;exportdefaultasyncfunctionDashboardPage(){constsessionawaitgetServerSession(authOptions);if(!session){redirect(/auth/signin);// Session 过期 → 重定向登录}return(divh1Welcome{session.user?.name}/h1pEmail:{session.user?.email}/p/div);} 好处SSR 阶段就能拦截未登录用户看不到敏感页面。对 SEO 友好页面不会闪一下再跳转。7.3 API 接口保护业务 API 路由里也要防止过期的 session// app/api/orders/route.tsimport{getServerSession}fromnext-auth;import{authOptions}from../auth/[...nextauth]/route;import{NextResponse}fromnext/server;exportasyncfunctionGET(){constsessionawaitgetServerSession(authOptions);if(!session){returnNextResponse.json({error:Unauthorized},{status:401});}returnNextResponse.json({orders:[{id:1,item:Book}]});}前端 fetchconstresawaitfetch(/api/orders);if(res.status401){router.push(/auth/signin);// 自动跳登录}7.4 用户体验优化自动续期如果你觉得「一天过期就要重新登录」很烦可以把maxAge设大一点比如 30 天配合updateAge比如 1 天只要用户每天来一次Cookie 就会自动刷新。session:{maxAge:60*60*24*30,// 30 天updateAge:60*60*24,// 每 24 小时刷新一次},这样就变成「长期有效登录」除非用户真的一个月没来。✅ 最终效果客户端检测→ 在 React 组件里实时监控登录状态失效自动跳转。服务端检测→ 在 page.tsx 里用getServerSession()未登录直接 redirect。API 接口保护→ 后端路由验证 session过期返回 401。自动续期→ 只要用户活跃session 就不会轻易过期。 感谢阅读想了解更多 我的博客网站 | 记录思考分享干货 我的个人主页 | 关于我、开源项目