
等候室(Waiting Room)
功能一项安全功能,在参与者加入主会议之前将其保留在虚拟大厅中
什么是等候室?
等候室是视频会议应用中的一项安全功能,可在参与者被允许加入主会议之前将其保留在虚拟大厅或等待区域。这使会议主持人或主持人能够控制谁进入会议,防止未经授权的访问,并减少会议期间的干扰。
等候室作为会议的入口点——参与者到达等候室并等待批准,而主持人或授权用户决定何时准入。这一功能在 2020 年代初变得尤为重要,当时"Zoom bombing"(未经授权的参与者破坏会议)成为一个常见的安全问题。
等候室的工作原理
参与者流程
- 加入请求:用户点击会议链接或输入会议 ID
- 等候室入场:用户被放置在等候室,而不是直接进入会议
- 通知主持人:主持人收到有新参与者正在等待的通知
- 等待批准:参与者看到一个屏幕,显示"主持人将很快让您进入"或类似消息
- 准入决定:主持人审查等待的参与者并决定准入、拒绝或从等候室移除他们
- 加入会议:获得批准后,参与者的 WebRTC 连接被建立并加入主会议
主持人控制
主持人通常有几个选项来管理等候室:
- 逐个准入:审查每个参与者并单独允许他们进入
- 全部准入:同时允许所有等待的参与者进入
- 拒绝准入:阻止特定参与者加入并将其从等候室移除
- 移至等候室:在会议期间将已经加入的参与者发送回等候室
- 禁用等候室:为后续参与者关闭等候室功能
实现架构
信令层面的等候室
等候室主要在信令层实现,而不是在 WebRTC 媒体层:
// 客户端:加入会议请求
socket.emit('join-meeting', {
meetingId: 'abc123',
userId: 'user456',
userName: 'Alice',
isHost: false
});
// 服务器:检查等候室状态
socket.on('join-meeting', async (data) => {
const meeting = await getMeeting(data.meetingId);
if (meeting.waitingRoomEnabled && !data.isHost) {
// 将用户放入等候室
addToWaitingRoom(data.meetingId, {
userId: data.userId,
userName: data.userName,
socketId: socket.id,
joinedAt: Date.now()
});
// 通知用户他们在等候室
socket.emit('waiting-room-status', {
status: 'waiting',
message: '主持人将很快让您进入会议'
});
// 通知主持人有新参与者正在等待
notifyHost(data.meetingId, {
type: 'new-participant-waiting',
userId: data.userId,
userName: data.userName
});
} else {
// 直接允许加入(主持人或禁用等候室)
allowJoinMeeting(socket, data);
}
});准入流程
当主持人批准参与者时:
// 主持人批准参与者
socket.on('admit-participant', async ({ meetingId, userId }) => {
// 验证请求者是主持人
if (!isHost(socket.id, meetingId)) {
return socket.emit('error', { message: '未授权' });
}
// 从等候室获取参与者
const participant = removeFromWaitingRoom(meetingId, userId);
if (participant) {
// 通知参与者他们已被准入
io.to(participant.socketId).emit('admitted-to-meeting', {
meetingId,
participants: getActiveParticipants(meetingId)
});
// 通知现有参与者有新用户加入
socket.to(meetingId).emit('participant-joined', {
userId: participant.userId,
userName: participant.userName
});
}
});WebRTC 连接时机
等候室的一个关键方面是何时建立 WebRTC 连接:
- 准入后连接(推荐):仅在参与者被准入后才建立对等连接。这节省服务器资源并防止未经授权的用户消耗带宽
- 准入前连接:在等候室建立连接但静音所有轨道。允许更快的加入,但消耗资源
大多数生产系统使用准入后连接方法以获得更好的安全性和资源管理。
用户界面设计
参与者视图
等候室界面通常包括:
- 状态消息:"等待主持人让您进入..."
- 会议信息:会议名称、时间、参与者数量
- 设备预览:摄像头和麦克风预览,以便用户可以在加入前进行测试
- 设置控制:音频/视频切换、设备选择、虚拟背景
- 离开选项:按钮可取消并离开等候室
- 可选聊天:某些系统允许等候室参与者向主持人发送消息
主持人视图
主持人的等候室管理界面显示:
- 等待列表:当前在等候室的所有参与者
- 参与者详情:姓名、加入时间、可选的个人资料图片
- 操作按钮:准入、拒绝、查看个人资料
- 批量操作:全部准入、全部拒绝
- 通知:新参与者加入等候室时的音频/视觉提醒
- 等候室切换:启用/禁用整个会议的等候室
安全益处
防止未经授权的访问
等候室提供几层安全保护:
- 主持人验证:主持人可以在允许访问之前验证参与者身份
- 防止会议破坏:阻止未知或未经授权的用户自动加入
- 控制时机:主持人可以在准备好之前阻止参与者加入(例如,在讨论敏感话题时)
- 审核日志:跟踪谁尝试加入以及何时加入,用于安全审核
隐私保护
等候室有助于保护隐私:
- 防止窃听:确保未经授权的用户无法默默加入并监听
- 受控暴露:参与者在明确获得批准之前不会看到或听到会议
- 选择性准入:主持人可以在准入某些参与者之前等待敏感讨论结束
配置选项
等候室设置
典型的等候室配置包括:
const meetingSettings = {
waitingRoom: {
enabled: true,
// 谁被发送到等候室
applyTo: 'all', // 'all', 'guests-only', 'non-registered'
// 自动准入规则
autoAdmit: {
enabled: false,
rules: [
{ type: 'authenticated-users', allow: true },
{ type: 'email-domain', domains: ['company.com'], allow: true }
]
},
// 主持人到达前
beforeHostJoins: 'waiting-room', // 或 'deny', 'allow'
// 自定义消息
customMessage: '请稍候,主持人将很快让您进入。',
// 超时
maxWaitTime: 30 * 60 * 1000, // 30 分钟后自动移除
}
};有条件的等候室
高级系统允许基于规则的等候室:
- 仅访客:已认证用户直接加入,访客进入等候室
- 首次参与者:以前加入过的参与者绕过等候室
- 基于域的:来自受信任域的用户自动获得准入
- 基于时间的:在会议开始前启用,在所有人到达后禁用
用户体验考虑
最佳实践
- 清晰的沟通:
- 向参与者解释他们为什么在等候室
- 提供等待时间的估计(如果可能)
- 显示等候室中还有多少人
- 快速准入:
- 使主持人能够轻松查看和准入参与者
- 当有人等待时提供音频/视觉通知
- 提供批量准入选项以加快速度
- 设备准备:
- 允许参与者在等候室测试他们的摄像头/麦克风
- 提供故障排除链接如果设备不工作
- 显示连接质量指标
- 优雅的拒绝:
- 如果拒绝参与者,提供清晰的消息
- 选择性地提供重新加入或联系主持人的方法
移动考虑
- 简化界面:等候室界面应在小屏幕上良好运行
- 通知:当准入时向移动用户发送推送通知
- 省电:等待时最小化资源使用
常见用例
- 企业会议:确保只有授权员工和批准的客人可以加入
- 网络研讨会:在活动开始前控制大量参与者的入场
- 教育:教师在上课开始前管理学生入场
- 医疗保健:医生在准备好之前控制患者准入以保护隐私
- 法律咨询:律师在敏感讨论前验证客户身份
- 董事会会议:确保只有董事会成员可以访问机密讨论
平台实现
- Zoom:提供可配置的等候室,主持人可以准入、拒绝或发送消息
- Google Meet:"敲门"功能,主持人在准入前看到参与者请求
- Microsoft Teams:大厅功能,具有基于角色的自动准入规则
- Whereby:"敲门"允许主持人在准入前查看参与者视频预览
技术挑战
主持人缺席
处理主持人尚未到达的情况:
- 队列参与者:在主持人加入之前将所有人保留在等候室
- 允许加入:如果没有主持人在场,允许参与者开始会议
- 联合主持人:指定可以准入参与者的联合主持人
可扩展性
对于有大量参与者的大型会议:
- 批量操作以有效管理大量参与者
- 过滤和搜索以在长列表中查找参与者
- 自动准入规则以减少手动工作
- 多个联合主持人以分配工作负载