Skip to content

Node.js 单设备登录(SDL)

SDL(Single Device Login)允许同一时间只在一台设备上登录,新设备登录时旧设备被挤下线。

应用场景

  • 视频影音(防账号共享)
  • 社交媒体(防未授权访问)
  • 在线支付(增强安全)
  • 邮箱通讯(保护隐私)

实现思路

使用 socket.io + 浏览器指纹 + Redis

js
// 数据结构
{
  userId: {
    socket: ws实例,
    fingerprint: '浏览器指纹'
  }
}

完整流程

1. 用户登录 → 生成 JWT token
              → 记录 fingerprint(用户代理 + 屏幕分辨率等)
              → 建立 socket.io 连接

2. 用户在新设备登录
   → 查询 Redis 发现已有 fingerprint 且不同
   → 通过 socket.io 向旧设备发送 'kickout' 事件
   → 旧设备收到 → 清除本地 token → 提示"已被挤下线"
   → 更新 Redis 记录为新设备信息

核心代码

js
import { Server } from 'socket.io'

const userSockets = {} // userId → { socket, fingerprint }

io.on('connection', (socket) => {
  // 登录时注册
  socket.on('login', ({ userId, fingerprint }) => {
    // 检查是否已有其他设备登录
    if (userSockets[userId] && userSockets[userId].fingerprint !== fingerprint) {
      // 通知旧设备下线
      userSockets[userId].socket.emit('kickout', '您的账号在其他设备登录')
    }
    // 记录新设备
    userSockets[userId] = { socket, fingerprint }
  })
})

浏览器指纹(简易版)

js
const fingerprint = navigator.userAgent + screen.width + screen.height

生产环境可用 fingerprint.js 等专业库生成更精确的指纹。