当前位置: 首页 > article >正文

SDL单设备登录

SDL单设备登录

需求:当账户在其他地方登录时,当前已登录账户会被顶下线

核心思路:
前后端建立WebSocket连接,当客户端登录账户,根据用户id保存Socket连接,如果该用户已有保存的连接,则通知下线并断开,然后更新连接

实现

Node 服务端

创建sdl.js实现核心逻辑

const { WebSocketServer } = require('ws')
const jwt = require('jsonwebtoken');

// 当前连接设备
let connection = {}
let wss = null

function setupSDL(server) {
  try {
    wss = new WebSocketServer({ server })
    wss.on('connection', (ws) => {
      ws.on('message', (message) => {
        const data = JSON.parse(message)
        if (data.action === 'login' && data.token) {
          let verifyResult = null
          jwt.verify(data.token, process.env.JWT_SECRET, (err, decoded) => {
            if (err) {
              console.log(err)
              return
            }
            verifyResult = decoded
          });
          if (!verifyResult) {
            return
          }
          if (connection[data.id] && connection[data.id].finggerprint) {
            console.log(`设备${data.id}已经登录`)
            // 设备已经登录
            connection[data.id].socket.send(JSON.stringify({
              action: 'logout',
              message: '您的账户已在其他设备登录,请重新登录'
            }))
            connection[data.id].socket.close()
            connection[data.id].socket = ws
            connection[data.id].token = data.token
            connection[data.id].finggerprint = data.finggerprint
          } else {
            connection[data.id] = {
              // 设备连接socket
              socket: ws,
              // token
              token: data.token,
              // 设备唯一标识
              finggerprint: data.finggerprint
            }
            console.log(`设备${data.id}登录成功`)
          }
        }
      })
    })
  } catch (error) {
    console.log(error)
  }
}

module.exports = {
  setupSDL,
  connection,
  wss
}
// 启动服务器
let server = app.listen(PORT, () => {
  console.log(`服务器正在运行在:http://localhost:${PORT}`);
});
setupSDL(server);  // 初始化sdl

客户端

项目初始化后new WebSocket连接,并监听登出的消息。每次用户登录都发送登录消息,如果当前已登录了发送登录消息(防止刷新丢失状态)

//浏览器指纹
const createBrowserFingerprint = () => {
  const canvas = document.createElement('canvas')
  const ctx: CanvasRenderingContext2D|null = canvas.getContext('2d')
  if (!ctx) {
    return
  }
  ctx.fillStyle = 'red'
  ctx.fillRect(0, 0, 1, 1)
  // return md5(canvas.toDataURL())
  console.log(canvas.toDataURL())
  return canvas.toDataURL()
}

var ws : WebSocket|null = null;
const connectionSdl = () => {
  ws = new WebSocket('ws://localhost:3200') //socket本地IP+端口
  ws.addEventListener('open', () => {
    // 已登录
    if(userStore.userInfo?.id && getToken()){
      ws!.send(JSON.stringify({
        action: 'login',
        id: userStore.userInfo.id,
        token: getToken(),
        finggerprint: createBrowserFingerprint()
      }))
    }
  })
  ws.addEventListener('message', (event) => {
    console.log(event.data)
    const data = JSON.parse(event.data)
    if (data.action === 'logout') {
      // 退出登录
      userStore.userLogout()
      ElMessage.error('您的账号在其他地方登录,请重新登录')
      // closeDialog()
    }
  })
}
connectionSdl()

每次用户登录都发送登录消息

if(ws && ws.readyState === 1){
    ws.send(JSON.stringify({
      action: 'login',
      id: userStore.userInfo.id,
      token: getToken(),
      finggerprint: createBrowserFingerprint()
    }))
  }

实现效果

用我自己写的一套项目的效果进行展示
在这里插入图片描述


http://www.kler.cn/a/456070.html

相关文章:

  • 云计算服务中 数据的所有权是谁的
  • Unity3D中Huatuo可行性的思维实验详解
  • 6-Gin 路由详解 --[Gin 框架入门精讲与实战案例]
  • pyQT + OpenCV相关练习
  • Artec Space Spider助力剑桥研究团队解码古代社会合作【沪敖3D】
  • 【Spring】配置文件的使用
  • 面试241228
  • 公路边坡安全监测中智能化+定制化+全面守护的应用方案
  • 开发过程优化·自定义鼠标右键菜单
  • hdfs balancer 指定节点做负载均衡
  • MySQL数据库的索引
  • 关于Nginx
  • Docker 常用总结
  • 深度学习笔记(4)——视频理解
  • PyQt实战——实现可视化音频播放器(十三)
  • 【LeetCode】839、相似字符串组
  • Cursor提示词
  • 【人工智能机器学习基础篇】——深入详解监督学习之回归与分类:理解线性回归、逻辑回归、支持向量机(SVM)、决策树、随机森林、梯度提升机(GBM)等算法
  • C语言勘破之路-最终篇 —— 预处理(下)
  • [文献阅读]ReAct: Synergizing Reasoning and Acting in Language Models
  • 1.FAISS与Langchain整合,搭配大模型实现本地知识库问答
  • 安卓执法仪Android接入国标GB28181平台实现实时监控、对讲、报警、定位等管理方案
  • 深度解析软件抽象:拨开层层迷雾,直击本质
  • JAVA 查询对象大小 查询当前JVM堆内存
  • 【智能制造-50】雅可比矩阵在机器人中如何应用
  • 使用Excel制作通达信自定义外部数据,安排!!!