websocket消息存库前必须参数化处理,因长连接特性使sql注入危害放大;须用preparedstatement等预编译方式,禁用字符串拼接;限制动态表/字段/操作符,校验json表达式并映射白名单;origin和token验证不能替代sql层防护。

WebSocket消息进数据库前必须做参数化处理
WebSocket本身不解析SQL,但很多开发者在@OnMessage或onMessage回调里直接拼接用户传来的字段去查库,比如"SELECT * FROM user WHERE name = '" + message + "'"——这和HTTP接口的SQL注入本质相同,只是入口换成了ws连接。
关键区别在于:WebSocket连接是长生命周期的,一次连接可能收几十上百条消息,每条都走同样逻辑;一旦某条消息触发注入,攻击者可反复利用该通道执行恶意查询。
- 永远不用字符串拼接构造SQL,无论消息来源是否“可信”(Origin头、Token等都可被篡改)
- 强制使用预编译语句:
PreparedStatement(Java)、pg.query带参数数组(Node.js)、session.execute(Python asyncpg) - 若用JPA/Hibernate,确保用
@Query(value = "...", nativeQuery = true)时也绑定参数,而非concat()或+拼接
不要在WebSocket处理器里直接调用动态构建的DAO方法
常见错误是把前端传来的table、field、op(如"LIKE"、"IN")全当参数透传给DAO层,再由DAO拼SQL。这等于把SQL语法控制权交给了客户端。
真实场景中,这类需求通常对应有限的几个业务动作(如“按用户名搜索”“查最近3条订单”),应预先定义白名单:
- 只允许
action字段取值为"searchUser"、"getRecentOrders"等固定枚举 - 每个action内部硬编码对应的表名、字段、WHERE条件结构,不接受任意字段名或操作符
- 用户输入仅作为值参与绑定,不参与SQL结构生成
警惕JSON消息里的嵌套SQL式字段
有些前端会发类似{"type":"filter","expr":"status = 'active' AND created_time > '2026-01-01'"}这种结构,后端直接塞进WHERE子句。这不是过滤,这是远程代码执行的变体。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
正确做法是把表达式解析成AST,再映射到预设规则:
- 用
JsonNode(Jackson)或JSONObject先校验字段层级和类型,拒绝expr含分号、括号嵌套超2层、出现UNION/EXEC等关键词 - 将合法的
status、created_time映射到内部字段白名单,操作符限定为eq、gt、in等安全子集 - 最终生成条件时仍走
PreparedStatement,不拼字符串
Origin和Token验证不能替代SQL层防护
很多人以为加了Origin检查、JWT校验就安全了,其实这只是防止未授权连接接入;一旦连接建立,后续所有onMessage调用都运行在已认证上下文中——攻击者只要拿到一个有效Token,就能通过WebSocket反复发送恶意payload。
所以防御必须落在数据访问层:
- 数据库账号权限最小化:WebSocket服务专用账号只具备
SELECT(或必要INSERT)权限,禁用CREATE、DROP、EXECUTE - 日志记录所有带用户输入的SQL执行(含参数值),便于事后追溯异常模式
- 对高频失败查询(如连续5次
SQLException)自动熔断该Session连接
最易被忽略的是:WebSocket消息没有Content-Type约束,前端可发任意格式文本,后端若用String.split()或正则提取字段再拼SQL,比JSON解析更难防御——这种原始解析方式必须彻底禁用。










