首页 > web前端 > js教程 > 正文

通过 JWT 授权,为基于 Node.js 和 WebSockets 的应用程序开发自定义二进制协议

WBOY
发布: 2024-08-26 21:47:32
原创
517 人浏览过

介绍

开发高效、安全的应用程序不仅需要经过深思熟虑的API,还需要正确选择数据传输协议。 Web 应用程序通常使用基于文本的格式,例如 JSONXML,但对于需要 最小延迟 和低数据传输量的高性能系统,它可以使用二进制协议是有利的。在本文中,我们将逐步介绍如何为 Node.js基于 WebSockets 的应用程序 开发自定义二进制协议,通过 JWT 添加授权,以及探索二进制协议相对于其他数据格式的优势。

Developing a custom binary protocol for Node.js and WebSockets based applications with authorization via JWT

为什么采用二进制协议?

二进制协议的优点:

  • 效率: 二进制协议比基于文本的格式(例如 JSON)更紧凑。它们允许以更压缩的形式传输数据,从而减少传输的流量。

  • 性能:二进制协议数据量少,无需解析文本格式,节省客户端和服务器端资源。

  • 安全性:与文本数据相比,二进制数据更难动态分析,这使得二进制协议更不容易受到攻击。

  • 灵活性:在二进制协议中,可以更精确地控制数据格式以适应特定的数据类型(例如浮点数、字符串、字节数组等)。

系统架构:

我们将开发一个由以下组件组成的系统:

  • Node.js 上的服务器,使用 WebSockets 与客户端通信。

  • JavaScript 客户端,连接到服务器并使用二进制协议传输数据。

  • 使用 JWT(JSON Web 令牌)进行授权,以安全地将客户端连接到服务器。

Node.js 上的服务器实现

依赖安装

首先,让我们安装必要的依赖项:

npm init -y
npm install ws jsonwebtoken
登录后复制

ws 是用于在服务器端使用 WebSocket 的库,jsonwebtoken 用于使用 JWT。

简单服务器代码:

const WebSocket = require('ws');
const jwt = require('jsonwebtoken');

// Our JWT Secret Key
const SECRET_KEY = 'your_secret_key';

// Create a new WebSocket Server
const wss = new WebSocket.Server({ port: 8080 });

// JWT Verification Function
function verifyJWT(token) {
    try {
        return jwt.verify(token, SECRET_KEY);
    } catch (e) {
        return null;
    }
}

// WebSocket Connection
wss.on('connection', (ws, req) => {
    // Get Token from Headers
    const token = req.url.split('token=')[1];
    const user = verifyJWT(token);

    // User is not Verified
    if (!user) {
        ws.close(4001, 'Unauthorized');
        return;
    }

    console.log(`User ${user.username} connected`);

    ws.on('message', (message) => {
        // Here we looking at message type. It must be a binary buffer
        if (message instanceof Buffer) {
            // Work with binary message
            const messageType = message.readUInt8(0); // First Byte - Message Type

            if (messageType === 1) { // If Message type is 1
                const textLength = message.readUInt16BE(1); // Get Message Length
                const text = message.toString('utf-8', 3, 3 + textLength);
                console.log(`Received message from ${user.username}: ${text}`);
            } else if(messageType === 2) {
                // Work with your message types
            }
        }
    });

    ws.on('close', () => {
        console.log(`User ${user.username} disconnected`);
    });
});

console.log('WebSocket server started on ws://localhost:8080');
登录后复制

代码说明:

  • JWT 授权: 服务器检查客户端在连接时传递的 JWT 令牌。如果令牌无效,服务器将关闭连接并出现授权错误。

  • 二进制数据处理:此示例假设客户端发送二进制数据。服务器通过逐字节读取数据来解析消息。例如,消息的第一个字节可以用作消息类型,后面是消息长度和数据本身。

  • WebSocket 服务器: ws 库用于管理连接和消息。

客户端实施

客户端代码

为了实现客户端,我们使用纯 JavaScript。

// Create Socket with our JWT Token
const socket = new WebSocket('ws://localhost:8080?token=your_jwt_token');

// Open Connection
socket.addEventListener('open', () => {
    console.log('Connected to server');

    // Binary Message example
    const message = "Hello, Binary World!";
    const buffer = new ArrayBuffer(3 + message.length);
    const view = new DataView(buffer);

    view.setUint8(0, 1); // Message type
    view.setUint16(1, message.length); // Message length
    for (let i = 0; i < message.length; i++) {
        view.setUint8(3 + i, message.charCodeAt(i));
    }

    socket.send(buffer);
});

// Get Response from server
socket.addEventListener('message', (event) => {
    if (event.data instanceof Blob) {
        event.data.arrayBuffer().then(buffer => {
            const view = new DataView(buffer);
            const messageType = view.getUint8(0);

            if (messageType === 1) { // Type 1 - Text Message
                const textLength = view.getUint16(1);
                const text = String.fromCharCode(...new Uint8Array(buffer.slice(3, 3 + textLength)));
                console.log(`Received message: ${text}`);
            }
        });
    }
});

// Close Connection
socket.addEventListener('close', () => {
    console.log('Disconnected from server');
});
登录后复制

代码说明:

  • 服务器连接: 客户端通过请求字符串传递 JWT 令牌来连接到 WebSocket 服务器。

  • 发送二进制数据:为了发送二进制数据,会创建一个ArrayBuffer,其中写入消息类型和文本数据。

  • 接收消息:客户端期望来自服务器的二进制数据,并使用 DataView 解析它以读取字节。

JWT 令牌创建和验证

在服务器端创建 JWT 令牌的示例:

const jwt = require('jsonwebtoken');

// Secret Key
const SECRET_KEY = 'your_secret_key';

// Example of JWT Token Generation
const token = jwt.sign({ username: 'user1' }, SECRET_KEY, { expiresIn: '1h' });
console.log(token);
登录后复制

此令牌可用于连接客户端。

结论

将二进制协议与 WebSockets 结合使用并通过 JWT 进行授权,可以为客户端-服务器通信提供高效且安全的系统。尽管二进制协议的实现很复杂,但它提供了显着的性能和数据减少优势。它们与高负载和资源密集型应用程序特别相关,在这些应用程序中,最小化延迟和网络利用率非常重要。

这种方法对于游戏开发、实时系统、金融应用程序以及其他需要高性能和可靠性的系统非常有用。

当然,感谢您的阅读。


您还可以支持编写教程、文章并查看适合您的项目的现成解决方案:

我的不和谐 | 我的博客 | 我的 GitHub | 给我买瓶啤酒

BTC: bc1qef2d34r4xkrm48zknjdjt7c0ea92ay9m2a7q55

ETH: 0x1112a2Ef850711DF4dE9c432376F255f416ef5d0

以上是通过 JWT 授权,为基于 Node.js 和 WebSockets 的应用程序开发自定义二进制协议的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!