websocket租户隔离需在握手阶段强制识别并校验租户标识,绑定至连接上下文;后续消息路由、存储、推送、日志及监控均须基于该租户id显式过滤与限制,严禁跨租户透传,并支持租户级连接生命周期管控。

WebSocket 本身不提供租户概念,隔离必须由业务层主动设计和控制。核心思路是:在连接建立初期就识别租户身份,并将该标识绑定到连接上下文;后续所有消息收发、路由、存储、推送都基于这个租户上下文做显式过滤和限制。
连接建立时强制提取并校验租户标识
不能依赖客户端传来的任意字段,必须在 WebSocket 握手阶段(HTTP Upgrade 请求)就完成租户识别与鉴权:
- 从 Host 头(如
tenant-a.example.com)解析子域名,这是最安全、不可伪造的方式 - 或从 URL 查询参数(如
wss://chat.example.com/?tenant_id=abc123)读取,但需配合签名或 JWT 校验防篡改 - 拒绝没有有效租户标识的连接请求,直接返回 403 或关闭握手
- 把租户 ID 安全存入 WebSocket 连接对象的自定义属性(如
ws.tenantId = 'abc123'),避免用闭包或全局变量缓存
消息路由阶段按租户维度严格分流
收到一条消息后,不直接广播或转发,而是先确认发送方和目标是否属于同一租户域:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 访客发消息 → 只能推送给同租户下的在线坐席(查 Redis 中
tenant:abc123:online:agents集合) - 坐席发消息 → 只能回传给同租户下指定会话的访客(需校验
session_id是否归属该租户) - 禁止跨租户消息透传,哪怕两个租户共用一个 WebSocket 服务进程
- 使用带租户前缀的 Redis Channel(如
chat:tenant-abc123:session-xyz)做发布/订阅,天然隔离
服务端存储与推送必须携带租户上下文
每条消息落地或中转时,都要打上租户标签,确保后续任何环节都能识别来源:
- 写入数据库前,自动补全
tenant_id字段(如用 Knex 的 query builder 插件或 TypeORM 的 QueryFilter) - 投递到消息队列(Kafka/RabbitMQ)时,在 headers 中注入
tenant_id,消费端据此做路由判断 - 日志记录统一添加
tenant_id字段,便于问题追踪和审计 - 监控指标(如连接数、消息吞吐)按租户分组聚合,避免一个租户异常拖垮整体视图
连接管理要支持租户级生命周期控制
租户下线、停服或违规时,需能精准下线其全部连接,不影响其他租户:
- 维护租户维度的连接映射表(如
Map<string set>></string>),增删连接时同步更新 - 提供管理接口(如
POST /api/admin/tenant/abc123/disconnect-all)触发批量断连 - 心跳检测失败后,只清理对应租户内的失效连接,不扫描全量连接池
- 连接关闭时,自动清理该租户相关的临时缓存(如会话状态、未读计数)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










