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()
    }))
  }

实现效果

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/944147.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL数据库函数——日期函数

常用的日期函数 函数功能curdate()返回当前日期curtime()返回当前时间now()返回当前日期和时间year(date)获取指定date的年份month(date)获取指定date的月份day(date)获取指定date的日期date_add(date,interval expr type)返回一个日期/时间值加上一个时间间隔expr后的时间值d…

基于MATLAB的冰箱水果保鲜识别系统

摘要:本作品旨在研究和实现基于MATLAB软件的冰箱水果保鲜识别系统,针对多种常见水果混合的图像进行处理和识别。首先,根据水果与背景的差异选择合适的阈值,对图像进行去噪和对比度增强,然后进行二值化处理。接下来&…

谷歌地球引擎GEE计算NDVI与NDWI的年平均值的方法

本文介绍在谷歌地球引擎(Google Earth Engine,GEE)中,基于哨兵2号遥感影像数据,计算某一指定区域NDVI、NDWI等指标的年平均值的方法。 本文是谷歌地球引擎(Google Earth Engine,GEE)…

《机器视觉:开启智能新时代》

《机器视觉:开启智能新时代》 一、机器视觉:工业之眼的崛起二、核心组件:构建精准视觉系统(一)光源:照亮视界的画笔(二)镜头:聚焦精准的慧眼(三)相…

RPA系列-uipath 学习笔记4

使用Uipath 处理hover的问题 备注:使用uipath stversion:2024.10.6,所有学习来源自uipath Academy 首先,打开uipath给我们提供的一个网站 ACME,这个网站呢,需要提前注册一下的哈。 今天呢,就是记录一下,怎…

Excel将混乱的多行做成1列

目标是将数据按从左到右,再从上到下排成一列。 公式法 首先用textjoin函数将文本包起来,做成一个超长文本。 然后用公式 截取文本 Mid(m1,n,3),意思就是对m1单元格,从第n个字符开始,截取3个字符出来。 这个公式如何自…

期权懂|期权入门知识:如何选择期权合约?

锦鲤三三每日分享期权知识,帮助期权新手及时有效地掌握即市趋势与新资讯! 期权入门知识:如何选择期权合约? 一、选择月份: 通常情况下,月份的选择与期货合约的选择类似,主要关注主力合约。主力…

ADC(三):注入组的使用

有关ADC的基础知识请参考标准库入门教程 ADC(三):注入组的使用 1、规则组软件触发注入组自动注入2、规则组外部触发注入组自动注入3、规则组软件触发注入组外部触发(TIM2_CC1)4、规则组软件触发注入组外部触发&#xf…

springboot整合log4j2日志框架1

一 log4j基本知识 1.1 log4j的日志级别 Log4j定义了8个级别的log(除去OFF和ALL,可以说分为6个级别),优先级从低到高依次为:All,trace,debug,info,warn,err…

Java - 日志体系_Simple Logging Facade for Java (SLF4J)日志门面_SLF4J集成JUL 及 原理分析

文章目录 官网集成Jdk_logging步骤POM依赖使用 原理分析SLF4J 与 JUL 的集成获取 ILoggerFactory 的过程根据 ILoggerFactory 获取 Logger 实例的过程 小结 官网 https://slf4j.org/ Simple Logging Facade for Java (SLF4J) 用作各种日志记录框架&…

爆肝1个月:DDR4 的信号完整性(万字长文SI)

前言: 大学里面,总有很多课程,很浪费时间,学了没点用处,问过老师,为什么信号完整性,示波器使用等课程不开呢,这种是对工作真实有帮助的? 老师:因为老师…

一文详解MacOS+CLion——构建libtorch机器学习开发环境

对于希望在本地环境中进行深度学习开发的开发者来说,配置合适的工具链是至关重要的一步。本文旨在帮助您在 macOS 操作系统上,利用 CLion IDE 和 PyTorch 的 C依赖库——libtorch,快速搭建起一个高效的开发环境。这里我们将一步步地讲解如何下…

pg数据库postgis扩展相关技术简介

postgis-note pg数据库postgis扩展相关技术简介 简介 PostGIS是在对象关系型数据库PostgreSQL上增加了存储管理空间数据的能力的开源GIS数据库。依托于PostgreSQL的两个重要特性:Geometry对象、Gist索引。 webgis技术路线 Geometry对象 Geometry(几…

Html——10 关键字和描述

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>淘宝网</title><meta name"keywords" content"我要自学网,自学HTML,自学CSS"/><meta name"description" content"要设置…

【原创学习笔记】近期项目中使用的西门子V20变频器总结(上篇)

现场V20 22kW变频器如图所示 进线分别为L1,L2,L3,PE线&#xff0c;出现分别为U,V,W接电机 在西门子官网查询手册后&#xff0c;查询可知可以通过多种方式控制变频器&#xff0c;比如&#xff1a;面板&#xff08;BOP&#xff09;控制&#xff0c;端子&#xff08;NPN/PNP&…

Exchange ProxyShell 攻击链利用详解

目录 ProxyShell CVE-2021-34473 SSRF ProxyShell 详细复现 ProxyShell 一键利用脚本 攻击者利用 ProxyShell 漏洞可绕过相关权限验证,进而配合其他漏洞可执行任意代码,控制Microsoft Exchange Server。 ProxyShell攻击链利用使用了以下漏洞: CVE-2021-34473 一个 SSR…

算法练习——模拟题

前言&#xff1a;模拟题的特点在于没有什么固定的技巧&#xff0c;完全考验自己的代码能力&#xff0c;因此有助于提升自己的代码水平。如果说一定有什么技巧的话&#xff0c;那就是有的模拟题能够通过找规律来简化算法。 一&#xff1a;替换所有问号 题目要求&#xff1a; 解…

ES 磁盘使用率检查及处理方法

文章目录 1. 检查原因2. 检查方法3. 处理方法3.1 清理数据3.2 再次检查磁盘使用率 1. 检查原因 磁盘使用率在 85%以下&#xff0c;ES 可正常运行&#xff0c;达到 85%及以上会影响 PEIM 数据存储。 在 ES 磁盘分配分片控制策略中&#xff0c;为了保护数据节点的安全&#xff0…

leetcode 面试经典 150 题:螺旋矩阵

链接螺旋矩阵题序号54题型二维数组&#xff08;矩阵&#xff09;解题方法模拟路径法难度中等熟练度✅✅✅ 题目 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3…

汽车CAN通信逻辑与LabVIEW开发

CAN通信的核心概念 CAN&#xff08;Controller Area Network&#xff09;是一种多主通信协议&#xff0c;广泛应用于汽车电子系统中&#xff0c;用于控制单元之间的高效通信。 ​ 消息优先级&#xff1a;每个CAN帧包含唯一的标识符&#xff08;ID&#xff09;&#xff0c;ID的…