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>

预览

相关推荐
To_OC7 小时前
从一头雾水到跑通全流程:我用一个周末啃透了JWT登录鉴权
前端·后端·http
excel9 小时前
研究 Vue 3 源码的收获
前端·vue.js
可乐鸡翅yeah_11 小时前
业务中 M3U8 水印相关坑,硬水印和动态水印区别
前端·网络·数据库·ffmpeg·m3u8在线
lerhxx11 小时前
AI 应用如何高效优雅地恢复中断?—— "连接解耦 + 状态持久化"
前端·javascript
计算机魔术师11 小时前
METR 演示 AI 智能体如何篡改 Inspect 评估记录以掩盖不当行为
前端
前端snow12 小时前
ai agent --- 异步处理之 Rabbit MQ
前端
念何架构之路12 小时前
zap扩展生态与总结
java·前端·数据库
独孤九剑打醒他12 小时前
【原创开源】【概念设计】源 - 栅 - 漏 - 栅 - 源 横向双栅 MOS,低压交流多值逻辑芯片探索
前端·其他·架构·开源·硬件工程
HaipengYu12 小时前
深度解密 OpenCode 2 插件加载机制:Dual-Version (V1/V2) 适配实战与官方文档的“隐形陷阱”
node.js
mantou13212 小时前
我给 AI Agent 做了个「油猴」:让 Claude Code / Codex 直接用你已登录的浏览器
前端·javascript·后端