介紹 Realtime API 的 Token 鑒權機制,包括 API Key 的擷取方式以及 WebSocket、WebRTC、AOQ 三種協議的建連鑒權方法。
Realtime API 使用 API Key 進行身份認證。無論選擇 AOQ、WebRTC 還是 WebSocket 通訊協定接入,均通過 HTTP 要求頭中的 Authorization 欄位攜帶 Bearer Token 完成身分識別驗證。
鑒權僅發生在建連階段,串連建立後的資料轉送無需重複鑒權。
三種協議的鑒權方式對比如下:
協議 | 鑒權時機 | 鑒權方式 | 說明 |
|---|---|---|---|
AOQ | 業務 AppServer 請求網關時 | HTTP Header | API Key 僅在服務端使用,用戶端使用網關返回的 Token |
WebRTC | SDP 交換 HTTP 要求時 | HTTP Header | 用戶端或服務端攜帶 API Key 發起 SDP 交換 |
WebSocket | WebSocket 串連握手時 | HTTP Header | 用戶端或服務端直接攜帶 API Key 建連 |
擷取 API Key
步驟 1:開通百鍊服務
- 訪問阿里雲百鍊控制台並登入您的阿里雲帳號。
- 如果是首次使用,按照頁面提示完成服務開通。
步驟 2:建立 API Key
- 在控制台左側導覽列中,選擇 API Key。
- 點擊 建立 API Key,選擇關聯的業務空間。
- 建立完成後,請立即複製並妥善儲存 API Key。
重要安全提示:API Key 是您訪問服務的唯一憑證,請勿將其寫入程式碼到用戶端代碼中或提交到代碼倉庫。建議通過環境變數或後端服務下發的方式管理。
建連鑒權詳解
AOQ 協議鑒權
AOQ 採用服務端代理鑒權模式:API Key 僅在業務 AppServer 側使用,用戶端通過網關返回的臨時 Token 建連,避免 API Key 暴露在用戶端。
curl -X POST \
"https://{endpoint}/api/v1/webrtc/realtime?model=qwen3.5-omni-plus-realtime" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${DASHSCOPE_API_KEY}" \
-H "x-dashscope-rtc-transport: moq" \
-d "{\"clientIp\": \"${CLIENT_REAL_IP}\"}"
curl -X POST \
"https://{endpoint}/api/v1/webrtc/inference?model=fun-asr-realtime" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${DASHSCOPE_API_KEY}" \
-H "x-dashscope-rtc-transport: moq" \
-d "{\"clientIp\": \"${CLIENT_REAL_IP}\"}"
參數說明
配置項 | 值 | 說明 |
|---|---|---|
endpoint | 根據業務情況選擇接入網域名稱 | 指定對應的接入網域名稱,詳情請參見選擇地區、服務部署範圍和接入網域名稱 |
Content-Type |
| 指定訊息類型 |
Authorization |
| 填寫API Key |
x-dashscope-rtc-transport |
| 指定使用 AOQ 協議 |
clientIp | 用戶端真實公網 IP | 選填。不填寫時,預設使用請求百鍊網關的 IP;填寫後以 clientIp 為準。Realtime API 會根據用戶端 IP 分配最佳的 Relay 存取點 |
響應樣本
{
"sid": "1d06b55683db49bba67a407902f62d02:1782706970:69aecdc5...",
"aoqTokenForClient": "ecc1a46015d5496ca4ff7a48281eb739",
"clientRelayEndpoints": [{"endpoint": "121.199.XX.XX", "port": 8443, "route_index": 0}],
"clientRelayCertFingerprint": "sha256/99843495...",
"sidExpiresInSecs": 7200,
"extraInfo": {"workspaceIdHash": "2021b6f98cea4cff"}
}
響應參數說明
欄位 | 說明 |
|---|---|
sid | 會話唯一標識 |
aoqTokenForClient | 用戶端串連令牌,傳給 SDK 的 token 欄位 |
clientRelayEndpoints | Relay 存取點數組(endpoint + port) |
clientRelayCertFingerprint | Relay TLS 認證指紋 |
sidExpiresInSecs | 會話到期時間(秒) |
extraInfo.workspaceIdHash | 工作區 ID 雜湊 |
AOQ Client SDK 串連樣本
說明clientIp 為請求體中的選填欄位。不填寫時,預設使用請求百鍊網關的 IP 作為用戶端 IP;填寫後則以指定的 clientIp 為準。建議由業務 AppServer 擷取用戶端真實 IP 後填入,以獲得最佳的 Relay 存取點。
let resp = try JSONDecoder().decode(AllocateResponse.self, from: responseData)
let config = AoqConnectConfig()
config.token = resp.aoqTokenForClient
config.sid = resp.sid
config.certFingerprint = resp.clientRelayCertFingerprint
config.relayEndpoints = resp.clientRelayEndpoints.enumerated().map { index, item in
let ep = AoqRelayEndpoint()
// route_index 預設時按數組下標兜底
ep.routeIndex = item.routeIndex ?? index
ep.endpoint = item.endpoint
ep.port = item.port
return ep
}
config.workspaceIdHash = resp.extraInfo?.workspaceIdHash ?? ""
let audioTrack = AoqTrackParam()
audioTrack.trackType = .audio
let dataTrack = AoqTrackParam()
dataTrack.trackType = .data
config.publishTracks = [audioTrack, dataTrack]
config.subscribeTracks = [audioTrack, dataTrack]
engine.connect(config)
JSONObject obj = new JSONObject(responseText);
AoqClientEngine.AoqConnectConfig cfg = new AoqClientEngine.AoqConnectConfig();
cfg.token = obj.optString("aoqTokenForClient", "");
cfg.sid = obj.optString("sid", "");
cfg.certFingerprint = obj.optString("clientRelayCertFingerprint", "");
JSONArray arr = obj.optJSONArray("clientRelayEndpoints");
if (arr != null) {
for (int i = 0; i < arr.length(); i++) {
JSONObject o = arr.optJSONObject(i);
AoqClientEngine.AoqRelayEndpoint ep = new AoqClientEngine.AoqRelayEndpoint();
// route_index 預設時按數組下標兜底
ep.routeIndex = o.has("route_index") ? o.optInt("route_index", i) : i;
ep.endpoint = o.optString("endpoint", "");
ep.port = o.optInt("port", 0);
cfg.relayEndpoints.add(ep);
}
}
JSONObject ext = obj.optJSONObject("extraInfo");
cfg.workspaceIdHash = ext != null ? ext.optString("workspaceIdHash", "") : "";
AoqClientEngine.AoqTrackParam audio = new AoqClientEngine.AoqTrackParam();
audio.trackType = AoqClientEngine.AoqTrackType.AoqTrackTypeAudio;
AoqClientEngine.AoqTrackParam data = new AoqClientEngine.AoqTrackParam();
data.trackType = AoqClientEngine.AoqTrackType.AoqTrackTypeData;
cfg.publishTracks.add(audio);
cfg.publishTracks.add(data);
cfg.subscribeTracks.add(audio);
cfg.subscribeTracks.add(data);
engine.connect(cfg);
const obj = JSON.parse(responseText) as Record<string, Object | undefined>;
const cfg: AoqConnectConfig = {
token: String(obj['aoqTokenForClient'] ?? ''),
sid: String(obj['sid'] ?? ''),
certFingerprint: String(obj['clientRelayCertFingerprint'] ?? ''),
// route_index 預設時按數組下標兜底
relayEndpoints: (obj['clientRelayEndpoints'] as Array<any>).map((item, index) => ({
routeIndex: Number(item['route_index'] ?? index),
endpoint: String(item['endpoint'] ?? ''),
port: Number(item['port'] ?? 0)
})),
workspaceIdHash: String((obj['extraInfo'] as any)?.['workspaceIdHash'] ?? ''),
publishTracks: [
{ trackType: AoqTrackType.AoqTrackTypeAudio },
{ trackType: AoqTrackType.AoqTrackTypeData }
],
subscribeTracks: [
{ trackType: AoqTrackType.AoqTrackTypeAudio },
{ trackType: AoqTrackType.AoqTrackTypeData }
]
};
engine.connect(cfg);
WebRTC 協議鑒權
WebRTC 通過 HTTP POST 請求完成 SDP 交換,鑒權在此階段完成。用戶端將 Offer SDP 發送至服務端,服務端返回 Answer SDP。
配置項 | 值 | 說明 |
|---|---|---|
要求方法 | POST | - |
請求地址 |
| 使用時替換 endpoint 和 model_name,不同模型的串連地址不同,詳情請參見WebRTC 接入 |
Content-Type |
| 請求體為 SDP 字串 |
Authorization |
| 填寫API Key |
響應 | HTTP 200,返回 Answer SDP | 失敗返回 4xx |
const pc = new RTCPeerConnection();
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
stream.getAudioTracks().forEach(t => pc.addTrack(t, stream));
pc.createDataChannel('oai-events');
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
// 等待 ICE 收集完成後發送
const resp = await fetch(API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/sdp',
'Authorization': `Bearer ${API_KEY}`,
},
body: pc.localDescription.sdp,
});
const answerSdp = await resp.text();
await pc.setRemoteDescription({ type: 'answer', sdp: answerSdp });
WebSocket 通訊協定鑒權
WebSocket 的鑒權方式最為簡單,在建立串連時直接通過 HTTP Header 攜帶 API Key 即可。
配置項 | 值 | 說明 |
|---|---|---|
串連地址 |
| 不同模型的串連地址不同,詳情請參見WebSocket 接入 |
Authorization |
| 填寫API Key |
import websocket, os
API_KEY = os.getenv("DASHSCOPE_API_KEY")
URL = "wss://dashscope.aliyuncs.com/api-ws/v1/realtime?model=qwen3.5-omni-plus-realtime"
ws = websocket.WebSocketApp(URL, header=["Authorization: Bearer " + API_KEY])
ws.run_forever()