Nodejs 第六十五章(SDL单设备登录)

单设备登录

SDL(Single Device Login)是一种单设备登录的机制,它允许用户在同一时间只能在一个设备上登录,当用户在其他设备上登录时,之前登录的设备会被挤下线。

应用场景

  1. 视频影音,防止一个账号共享,防止一些账号贩子
  2. 社交媒体平台:社交媒体平台通常有多种安全措施来保护用户账户,其中之一就是单设备登录。这样可以防止他人在未经授权的情况下访问用户的账户,并保护用户的个人信息和隐私
  3. 对于在线购物和电子支付平台,用户的支付信息和订单详情是敏感的。通过单设备登录,可以在用户进行支付操作时增加额外的安全层级,确保只有授权设备可以进行支付操作
  4. 对于电子邮箱和通讯应用,用户的个人和机密信息都存储在其中。通过单设备登录机制,可以确保用户的电子邮箱或通讯应用只能在一个设备上登录,避免账户被他人恶意使用

实现思路

设计数据结构

js 复制代码
{
 id:{
    socket:ws实例
    fingerprint:浏览器指纹
  }
}
  1. 第一次登录的时候记录用户id,并且记录socket信息,和浏览器指纹
  2. 当有别的设备登录的时候发现之前已经连接过了,便使用旧的socket发送下线通知,并且关闭旧的socket,更新socket替换成当前新设备的ws连接

浏览器指纹

指纹技术有很多种,这里采用canvas指纹技术

网站将这些颜色数值传递给一个算法,算法会对这些数据进行复杂的计算,生成一个唯一的标识。由于用户使用的操作系统、浏览器、GPU、驱动程序会有差异,在绘制图形的时候会产生差异,这些细微的差异也就导致了生成的标识(哈希值)不一样。因此,每一个用户都可以生成一个唯一的Canvas指纹

实现代码

nodejs端

js 复制代码
import express from 'express'
import { WebSocketServer } from 'ws'
import cors from 'cors'
const app = express()
app.use(cors())
app.use(express.json())
//存放数据结构
const connection = {}

const server = app.listen(3000)
const wss = new WebSocketServer({ server })

wss.on('connection', (ws) => {
    ws.on('message', (message) => {
        const data = JSON.parse(message)
        if (data.action === 'login') {
            if (connection[data.id] && connection[data.id].fingerprint) {
                console.log('账号在别处登录')
                //提示旧设备
                connection[data.id].socket.send(JSON.stringify({
                    action:'logout',
                    message:`你于${new Date().toLocaleString()}账号在别处登录` 
                }))
                connection[data.id].socket.close() //断开旧设备连接
                connection[data.id].socket = ws //更新ws
            } else {
                console.log('首次登录')
                connection[data.id] = {
                    socket: ws, //记录ws
                    fingerprint: data.fingerprint //记录指纹
                }
            }
        }
    })
})

浏览器端

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <h1>SDL</h1>
    <script src="./md5.js"></script>
    <script>
       //浏览器指纹
        const createBrowserFingerprint = () => {
            const canvas = document.createElement('canvas')
            const ctx = canvas.getContext('2d')
            ctx.fillStyle = 'red'
            ctx.fillRect(0, 0, 1, 1)
            return md5(canvas.toDataURL())
        }
        //谷歌abf12f62e03d160f7f24144ef1778396
        //火狐80bea69bfc7cad5832d12e41714cf677
        //Edge abf12f62e03d160f7f24144ef1778396

        const ws = new WebSocket('ws://192.168.120.145:3000') //socket本地IP+端口
        ws.addEventListener('open', () => {
            ws.send(JSON.stringify({
                action: 'login', //动作登录
                id: 1, //用户ID
                fingerprint: createBrowserFingerprint() //浏览器指纹
            }))
        })
        ws.addEventListener('message', (message) => {
            const data = JSON.parse(message.data)
            if (data.action === 'logout') {
                alert(data.message) //监听到挤下线操作提示弹框
            }
        })

    </script>
</body>

</html>

预览

相关推荐
安冬的码畜日常3 分钟前
【CSS in Depth 2 精译_032】5.4 Grid 网格布局的显示网格与隐式网格(上)
前端·css·css3·html5·网格布局·grid布局·css网格布局
洛千陨3 分钟前
element-plus弹窗内分页表格保留勾选项
前端·javascript·vue.js
小小19925 分钟前
elementui 单元格添加样式的两种方法
前端·javascript·elementui
前端没钱25 分钟前
若依Nodejs后台、实现90%以上接口,附体验地址、源码、拓展特色功能
前端·javascript·vue.js·node.js
爱喝水的小鼠30 分钟前
AJAX(一)HTTP协议(请求响应报文),AJAX发送请求,请求问题处理
前端·http·ajax
dgiij31 分钟前
AutoX.js向后端传输二进制数据
android·javascript·websocket·node.js·自动化
叫我:松哥1 小时前
基于机器学习的癌症数据分析与预测系统实现,有三种算法,bootstrap前端+flask
前端·python·随机森林·机器学习·数据分析·flask·bootstrap
让开,我要吃人了1 小时前
HarmonyOS鸿蒙开发实战(5.0)网格元素拖动交换案例实践
前端·华为·程序员·移动开发·harmonyos·鸿蒙·鸿蒙开发
CaptainDrake1 小时前
包管理工具
npm·node.js
谢尔登1 小时前
Webpack 和 Vite 的区别
前端·webpack·node.js