业务后端怎样让用户安全入会
第三方业务后端知道自己的用户和会议成员关系。它先校验业务用户,再用保存在服务端的 AKStream.Next API Token 建立房间或签发一次性入会票据。浏览器和 App 只接收本人的票据,不接收管理员密码或长期 API Token。
flowchart LR
U["业务用户登录你的系统"] --> B["业务后端核对会议资格"]
B --> A["AKStream.Next 签 accessTicket"]
A --> C["指定设备调用 RTC SDK join"]
C --> T["SDK 持有并续签当前设备 RTC Token"]
后端要做的三步
- 按你的业务规则决定用户是否能进入这个会议,以及是主持人、发言人还是只看成员。
- 用只存在于后端的 API Token 创建或选择房间;
mediaServerId必须指向实际已登记的媒体节点。 - 通过
POST /api/v2/rtc/rooms/{roomId}/access-tickets为该用户签票,将响应里的roomId和accessTicket只交给这一次入会的设备。
请求示例(subjectId 应取自后端已验证的业务用户,不接受客户端自行决定):
POST /api/v2/rtc/rooms/{roomId}/access-tickets
Authorization: Bearer <后端保管的 API Token>
Content-Type: application/json
{"subjectIssuer":"business-app","subjectId":"user-1001","displayName":"张三","role":"viewer","capabilities":["publications.subscribe"],"expiresInMinutes":5,"bypassWaitingRoom":false}
这是只看成员。需要发布麦克风或摄像头时,由业务后端根据资格改为相应角色并请求 microphone.publish、camera.publish 能力;服务端仍会按房间策略取交集。一次性票据有期限且只能消费一次,失败重试时先判断票据是否已经被消费,再向后端申请新票。
如果业务后端使用 Node.js 的标准 fetch,下面的函数可以放在已验证业务登录的服务端路由中。user.id 与 canSpeak 必须由服务端得出,不能照收网页传来的角色。运行前在服务端设置 AKSTREAM_URL 与 AKSTREAM_API_TOKEN:
export async function issueRtcTicket(roomId, user, canSpeak) {
const base = process.env.AKSTREAM_URL
const token = process.env.AKSTREAM_API_TOKEN
if (!base || !token || !roomId || !user?.id) throw new Error('缺少服务配置或已验证的用户')
const response = await fetch(new URL(`/api/v2/rtc/rooms/${encodeURIComponent(roomId)}/access-tickets`, base), {
method: 'POST',
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
subjectIssuer: 'business-app',
subjectId: String(user.id),
displayName: String(user.displayName || user.id),
role: canSpeak ? 'speaker' : 'viewer',
capabilities: canSpeak
? ['microphone.publish', 'camera.publish', 'publications.subscribe', 'chat.send']
: ['publications.subscribe'],
expiresInMinutes: 5,
bypassWaitingRoom: false
}),
signal: AbortSignal.timeout(15000)
})
if (!response.ok) throw new Error(`AKStream.Next 签票失败:HTTP ${response.status}`)
const ticket = await response.json()
return { roomId, accessTicket: ticket.accessTicket, expiresAtUtc: ticket.expiresAtUtc }
}
先用普通只看用户调用,确认返回的 roomId 与请求一致且票据非空;随后在客户端入会。401 查服务端 API Token,403 查 rtc.manage 与该房间的业务授权,429 按限流结果等待,不要反复签票。日志只记状态码和业务请求 ID,不记录完整 accessTicket。
客户端拿到票后
调用目标端 SDK 的 join/joinWithAccessTicket,由 SDK 处理参会令牌续签、信令与媒体会话。返回 Waiting 时停在等候页面,不自行发布;主持准入后根据 SDK 事件继续。participantId 指当前会议成员,deviceSessionId 指一次设备会话,同一用户多设备不能按姓名合并成一台。
服务器需要终端可达的 HTTPS 地址和媒体端口,证书必须与设备实际访问的域名或 IP 匹配。网页能打开不等于 ICE 媒体可通。设置方法见端口、域名和 HTTPS。
进入会议后页面从 SDK 读取状态,不保存或解码 RTC Token。用户离会时调用 SDK leave;只关闭网页或 Activity 不能保证服务器立即释放设备会话。下一步按端类型选择接入指南。