You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 06:16:16