Next.js应用中如何获取用户在线状态与最后活跃时间
问题:NextAuth无会话存储下实现用户在线状态与最后活跃时间
我的NextAuth关键配置
callbacks: { async jwt({ token, user }) { if (user) { token.id = user.id; token.email = user.email; token.role = user.role; token.nickname = user.nickname; } return token; }, async session({ session, token }) { if (session?.user) { session.user.id = token.id as string; session.user.email = token.email as string; session.user.role = token.role as string; session.user.nickname = token.nickname as string; } return session; } }, session: { strategy: "jwt", maxAge: 600, }, jwt: { maxAge: 600 }
问题描述
由于未存储会话,我不清楚如何获取用户在线状态的实时更新。我知道需要用到Websocket,但Next.js对Socket.io的支持并不理想。我想获取应用中用户的在线状态与最后活跃时间,请问是否有可行的替代方案?
我曾尝试在Express上搭建Websocket应用,但遇到大量CORS错误,且考虑到应用将部署在Vercel上,该方案显然不可行,因此寻求其他实现该功能的方法。
可行替代方案
1. Server Sent Events (SSE) + Redis
SSE是轻量级单向服务器推送技术,适配Vercel无服务器环境:
- 在Next.js中创建API路由(如
app/api/online-status/route.ts),处理客户端的SSE连接 - 客户端页面加载时发起SSE连接,定期发送心跳请求,服务器将用户ID和最后活跃时间写入Redis
- 其他客户端查询在线状态时,调用API从Redis读取数据,通过判断最后活跃时间是否在阈值内(如1分钟)标记在线状态
2. 定期API心跳 + Redis
无需实时推送,实现成本低:
- 用户登录后,客户端每隔30秒调用
app/api/update-active/route.ts,携带从JWT解析出的用户ID - 服务器路由接收请求后,更新Redis中对应用户的最后活跃时间
- 查询在线状态时,直接从Redis读取用户最后活跃时间,对比阈值判断是否在线
3. 托管式实时服务(如Pusher)
如果需要实时推送状态变更,用托管服务规避Websocket部署问题:
- 客户端登录后,通过托管服务建立连接,触发"user-online"事件,服务器将状态写入Redis
- 其他客户端订阅对应频道,接收状态变更的实时推送
- 托管服务已处理CORS和连接维护,直接在Next.js中集成即可,适配Vercel部署
适配NextAuth JWT策略的注意事项
- 所有API路由可通过NextAuth的
getToken方法解析JWT获取用户ID,无需额外会话存储 - 合理设置心跳间隔(如30秒)和在线阈值(如1分钟),平衡实时性与服务器负载
- 选择Redis作为状态存储,Vercel原生支持Redis集成,适合存储键值对类型的在线状态数据
内容的提问来源于stack exchange,提问作者Rafay Jamal
相关产品推荐
相关产品推荐

