WebSocket数据加密传输方法 WebSocket内容加密解密方案【实战】

幻夢星雲

幻夢星雲

2026-05-30

598人浏览

原创

wss://仅保障传输层tls安全,无法防止终端被控或tls终止点后明文泄露,必须在应用层用aes-gcm等方案做端到端加密。

websocket数据加密传输方法 websocket内容加密解密方案【实战】

WebSocket 本身不加密消息内容,wss:// 只保障传输层(TLS)安全,一旦终端被控或 TLS 被绕过,明文消息仍可被直接读取。真正在生产环境防窃听、防篡改,必须做应用层端到端加密。

为什么不能只靠 wss://

很多人上线后只配了 Nginx 的 wss 代理,就以为“已经加密了”,结果审计时发现聊天记录、用户 ID、金额字段全是明文 JSON。这是因为:

  • wss 加密的是 TCP 流,解密发生在 Nginx 或服务端 TLS 终止点之后——从 Nginx 到后端 WebSocket 服务(如 Spring Boot、Ratchet、Netty)之间走的是普通 ws:// 或内网 HTTP 协议,数据是裸奔的
  • 浏览器内存 dump、调试器 hook、恶意扩展都能在 onmessage 回调前/后截获原始消息
  • 服务端日志若未脱敏,console.log(event.data) 会把解密后的内容打满日志系统

前端用 Web Crypto API 做 AES-GCM 加密

别再引入 CryptoJS 或硬编码密钥。现代浏览器原生支持 window.crypto.subtle,更安全、无依赖、性能好。重点不是“能不能加”,而是“怎么加才不白加”:

  • 密钥必须由服务端动态下发,绑定 session_id 或短期 access_token,绝不能写死在 JS 里
  • 固定使用 AES-GCM:它自带认证标签(tag),解密失败直接丢弃,避免填充预言攻击
  • IV 必须每次随机生成且长度为 12 字节(96 bit),和密文一起 base64 传给服务端;不要复用 IV
  • 加密前把消息转成 Uint8Array,不要对字符串直接 encodeURI —— 中文会乱码
  • 附加数据(additionalData)建议传时间戳 + client_id,服务端解密后校验是否超时/来源合法

示例片段(发送端):

WebSocket 8.18.2
WebSocket 8.18.2

WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。

下载
const encoder = new TextEncoder();
const data = encoder.encode(JSON.stringify({ action: 'transfer', amount: 1000 }));
const iv = window.crypto.getRandomValues(new Uint8Array(12));
const key = await importKeyFromServer(); // 从服务端获取的密钥

const encrypted = await window.crypto.subtle.encrypt(
  { name: 'AES-GCM', iv, additionalData: encoder.encode(Date.now() + clientId) },
  key,
  data
);

const msg = {
  iv: btoa(String.fromCharCode(...iv)),
  data: btoa(String.fromCharCode(...new Uint8Array(encrypted))),
  tag: btoa(String.fromCharCode(...new Uint8Array(encrypted).slice(-16)))
};

服务端解密必须严格对齐参数

前后端 AES-GCM 参数错一个字节,就会解密失败。常见翻车点:

  • 前端用 12 字节 IV,服务端却按 16 字节解析(比如误用 AES-CBC 模式逻辑)
  • 前端传的 tag 是最后 16 字节,服务端没截取、或截多了/少了
  • 服务端用 UTF-8 解码 base64 后的密文,但前端加密的是原始字节数组(需用 BufferUint8Array 处理)
  • 没校验 additionalData:攻击者重放旧消息,只要密钥没换就能通过解密

以 PHP 为例,关键校验代码:

$iv = base64_decode($payload['iv']);
$ciphertext = base64_decode($payload['data']);
$tag = base64_decode($payload['tag']);
$full_ciphertext = $ciphertext . $tag;

// 必须指定 tag length,否则 openssl_decrypt 自动忽略认证
$decrypted = openssl_decrypt($full_ciphertext, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag, $additionalData);

密钥管理最容易被忽视的三个动作

90% 的前端加密失效,不是算法问题,而是密钥生命周期失控:

  • 密钥导入后,立刻清空原始字符串变量:keyStr = null;别让它留在内存可被 console.memory 扫描到
  • 解密完成的明文数据,不要赋值给全局对象或 Vue data 属性长期驻留;用完即 JSON.parse() 后立即丢弃原始 ArrayBuffer
  • 服务端下发密钥时,HTTP 响应头加上 Cache-Control: no-store, no-cache,防止被 CDN 或浏览器缓存

真正难的不是写加解密函数,而是让密钥不落地、不驻留、不复用。每次连接都该有独立密钥上下文,断连即销毁——这点在长连接频繁重连的场景里,最容易被跳过。

相关专题

更多
C语言变量命名
C语言变量命名

c语言变量名规则是:1、变量名以英文字母开头;2、变量名中的字母是区分大小写的;3、变量名不能是关键字;4、变量名中不能包含空格、标点符号和类型说明符。php中文网还提供c语言变量的相关下载、相关课程等内容,供大家免费下载使用。

2023.06.20

1349

3

c语言入门自学零基础
c语言入门自学零基础

C语言是当代人学习及生活中的必备基础知识,应用十分广泛,本专题为大家c语言入门自学零基础的相关文章,以及相关课程,感兴趣的朋友千万不要错过了。

2023.07.25

1535

9

c语言运算符的优先级顺序
c语言运算符的优先级顺序

c语言运算符的优先级顺序是括号运算符 > 一元运算符 > 算术运算符 > 移位运算符 > 关系运算符 > 位运算符 > 逻辑运算符 > 赋值运算符 > 逗号运算符。本专题为大家提供c语言运算符相关的各种文章、以及下载和课程。

2023.08.02

691

5

c语言数据结构
c语言数据结构

数据结构是指将数据按照一定的方式组织和存储的方法。它是计算机科学中的重要概念,用来描述和解决实际问题中的数据组织和处理问题。数据结构可以分为线性结构和非线性结构。线性结构包括数组、链表、堆栈和队列等,而非线性结构包括树和图等。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.09

551

4

c语言random函数用法
c语言random函数用法

c语言random函数用法:1、random.random,随机生成(0,1)之间的浮点数;2、random.randint,随机生成在范围之内的整数,两个参数分别表示上限和下限;3、random.randrange,在指定范围内,按指定基数递增的集合中获得一个随机数;4、random.choice,从序列中随机抽选一个数;5、random.shuffle,随机排序。

2023.09.05

909

5

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

2023.09.20

1127

7

c语言get函数的用法
c语言get函数的用法

get函数是一个用于从输入流中获取字符的函数。可以从键盘、文件或其他输入设备中读取字符,并将其存储在指定的变量中。本文介绍了get函数的用法以及一些相关的注意事项。希望这篇文章能够帮助你更好地理解和使用get函数 。

2023.09.20

1661

8

c数组初始化的方法
c数组初始化的方法

c语言数组初始化的方法有直接赋值法、不完全初始化法、省略数组长度法和二维数组初始化法。详细介绍:1、直接赋值法,这种方法可以直接将数组的值进行初始化;2、不完全初始化法,。这种方法可以在一定程度上节省内存空间;3、省略数组长度法,这种方法可以让编译器自动计算数组的长度;4、二维数组初始化法等等。

2023.09.22

5489

6

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

2023.09.22

419

3

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WebSocket手册
WebSocket手册

共0课时 | 0人学习

Webman中文手册
Webman中文手册

共0课时 | 0人学习

Workerman官方手册
Workerman官方手册

共0课时 | 0人学习