Skip to content

登录鉴权

WebSocket 行情推送连接建立后,需要先发送登录鉴权帧。鉴权成功前不要发送订阅请求;鉴权失败、连接关闭或超时未返回鉴权结果时,应关闭当前连接,修正凭证后重新连接并重新鉴权。

INFO

本文描述的是当前 WebSocket 接入层支持的鉴权帧形态。后端行情订阅服务本身不直接校验公网访问凭证,而是接收接入层完成鉴权后的会话上下文。因此,开发者只需要关注 WebSocket 连接后的首帧鉴权、鉴权结果处理和后续订阅流程,不需要也不应传入内部会话字段。

前置条件

开始前请确认已经完成以下准备:

  1. 已根据 快速开始 获取可用的访问凭证。
  2. 已连接 WebSocket Quote 地址:
text
wss://webapi-quote.moomoo.com
  1. 当前账号已具备对应市场、品类和行情档位权限。权限会影响可订阅的数据类型、买卖盘深度和实际推送内容。

鉴权方式

WebSocket 行情推送支持两类接入方式:

方式推荐程度适用场景说明
OAuth 2.1 + PKCE推荐第三方应用、桌面应用、移动端应用、Web 应用等需要用户授权的场景使用 access_token 作为 Bearer Token 完成 WebSocket 登录鉴权。
API Key兼容服务端自有系统、后端任务、内部工具等由开发者自行管理密钥的场景使用 AppKey、时间戳、随机串和签名完成 WebSocket 登录鉴权。

推荐使用 OAuth

OAuth 方式无需在客户端保存 API 私钥,也无需为每次接入手工管理签名材料。除非已有服务端 API Key 接入或有明确兼容需求,建议优先使用 OAuth 2.1 + PKCE。

鉴权帧格式

连接建立后,客户端应将鉴权帧作为首个业务消息发送:

字段类型必填说明
actionstring固定为 auth
data.auth_typestring鉴权类型。OAuth 使用 oauth2,API Key 使用 appkey
data.authorizationstringOAuth 场景传 Bearer {access_token};API Key 场景传签名结果。

OAuth 鉴权示例

先按 快速开始:OAuth 2.1 + PKCE 获取 access_token,再在 WebSocket 连接打开后发送以下 JSON:

json
{
  "action": "auth",
  "data": {
    "auth_type": "oauth2",
    "authorization": "Bearer {access_token}"
  }
}

说明:

  • authorization 必须包含 Bearer 前缀。
  • access_token 过期或无效时,鉴权会失败。请使用 refresh_token 刷新后重新建立 WebSocket 连接并重新鉴权。
  • 请确认用户授权范围覆盖行情读取能力;权限不足时,后续订阅可能失败或无法收到对应类型的数据。

Token 安全

不要把 access_tokenrefresh_token 写入前端可公开访问的静态配置、日志或错误上报。服务端应用应使用安全存储;桌面或移动端应用应使用系统密钥链、加密存储等机制。

API Key 鉴权示例

API Key 方式适合服务端持有私钥的场景。请先按 快速开始:传统 API Key 创建 AppKey、上传公钥并安全保存私钥。

WebSocket 鉴权帧的高层结构如下:

json
{
  "action": "auth",
  "data": {
    "auth_type": "appkey",
    "credential_id": "{app_key}",
    "authorization": "{signature_base64}",
    "timestamp_ms": 1782357937000,
    "nonce": "{nonce}"
  }
}

字段说明:

字段类型必填说明
credential_idstringAppKey ID。
authorizationstring使用 AppKey 私钥生成的签名结果,通常为 Base64 编码后的签名字符串。
timestamp_msint64客户端当前毫秒时间戳。
noncestring客户端随机字符串,用于防重放。

API Key 签名规则

WebSocket API Key 鉴权与 REST API Key 调用使用同一套 AppKey / 公钥 / 私钥身份体系,但签名原文格式与 REST 不同。

WebSocket 鉴权签名原文格式(字段间用 \n 分隔):

text
{timestamp_ms}\n{nonce}\nWEBSOCKET\nws/auth

不要直接复用 REST 请求的签名原文。

私钥安全

API Key 私钥只应保存在开发者自己的安全服务端或受控运行环境中。不要把私钥下发到浏览器、移动端安装包、客户端配置文件或代码仓库。

鉴权结果处理

客户端发送鉴权帧后,应等待服务端返回鉴权结果,再继续发送订阅请求。

建议按以下方式处理:

场景处理建议
鉴权成功记录连接进入已鉴权状态,然后发送订阅请求。订阅格式见 订阅与反订阅
返回错误不要继续订阅。根据错误信息检查 Token、AppKey、签名、时间戳、权限等配置。
服务端关闭连接视为当前连接不可用。修正凭证或等待退避时间后重新连接、重新鉴权。
等待超时主动关闭连接并重试。避免在未知鉴权状态下发送订阅请求。

鉴权成功响应

鉴权成功时,服务端返回以下 JSON:

json
{
  "id": "req-001",
  "session_id": "123456789",
  "server_time": 1782357937000000
}
字段类型说明
idstringEcho 请求 ID,请求未传时省略。
session_idstring服务端分配的会话 ID。
server_timeint64服务器时间,微秒级时间戳。

当前接入层在鉴权成功后会建立后续订阅所需的会话上下文。客户端无需解析或传递内部路由字段,例如 uidsession_idconn_id、行情权限画像或配额字段;这些字段由接入层和后端服务内部处理。

通道刷新

鉴权成功后,可在已建立的连接上发送刷新帧以更新会话票据。刷新成功后,已有订阅不中断,继续正常推送。

刷新频率要求

客户端应至少每 10 分钟发送一次刷新帧。若超过 10 分钟未主动刷新,服务端将主动断开连接。建议以 5 分钟为周期定时发送刷新帧,预留容错次数。

OAuth 刷新

使用 refresh_token 在后台换取新的 access_token 后,发送以下刷新帧:

json
{
  "action": "refresh",
  "data": {
    "authorization": "Bearer {new_access_token}"
  }
}

说明:

  • 建议在 Token 过期前主动刷新,避免因 Token 失效导致会话中断。
  • authorization 必须包含 Bearer 前缀。

API Key 刷新

json
{
  "action": "refresh",
  "data": {
    "credential_id": "{app_key}",
    "authorization": "{new_signature_base64}",
    "timestamp_ms": 1782357938000,
    "nonce": "{new_nonce}"
  }
}

说明:

  • timestamp_msnonce 必须使用与上次鉴权不同的新值,不能重复使用。
  • 签名原文格式与初始鉴权相同:{timestamp_ms}\n{nonce}\nWEBSOCKET\nws/auth

刷新成功响应

刷新成功时,服务端返回与初始鉴权相同格式的响应:

json
{
  "id": "req-002",
  "session_id": "123456789",
  "server_time": 1782357938000000
}

session_id 保持不变,server_time 更新为当前服务器时间。

如果刷新失败,请检查新凭证是否有效;连续刷新失败时,可关闭连接后用新凭证重新建立连接并重新鉴权。

与订阅权限的关系

登录鉴权只确认“当前连接是谁”和“凭证是否有效”。实际能否订阅某个标的或数据类型,还会受到以下因素影响:

  • 账号是否具备对应市场和品类的行情权限。
  • 行情权限档位是否支持对应数据类型或深度,例如 LV1 / LV2 / LV3 对买卖盘深度的影响。
  • 当前账号或权限层级的订阅配额是否足够。
  • 标的代码是否有效,且是否支持对应推送类型。

因此,鉴权成功不等于所有订阅都会成功。订阅请求仍需要根据响应结果处理成功、失败、权限不足和配额不足等情况。

连接生命周期建议

  • 先鉴权再订阅:每次新建 WebSocket 连接后,都应先发送鉴权帧,等待成功后再订阅。
  • 断线后重新鉴权:连接断开后不要假设原连接的鉴权状态仍然有效。请重新连接、重新鉴权、重新订阅。
  • 定时发送刷新帧:鉴权成功后,客户端须每隔不超过 10 分钟发送一次刷新帧,建议周期为 5 分钟。超过 10 分钟未刷新,服务端将主动断开连接。OAuth 场景同时也应在 Token 过期前完成刷新;API Key 场景同样需要定时刷新以维持会话。详见 通道刷新
  • 不要复用内部会话字段:服务端返回或日志中可能出现的会话标识仅用于接入层和后端路由,不应作为公开订阅参数持久化或复用。
  • 做好退避重试:连续鉴权失败时,应检查凭证配置并采用指数退避,避免高频重连。

常见问题

可以在一个连接上重新发送鉴权帧切换用户吗?

不建议。一个 WebSocket 连接应对应一次明确的登录鉴权上下文。如需切换用户、账号或凭证,请关闭旧连接,使用新凭证重新连接并重新鉴权。

OAuth 和 API Key 可以混用吗?

单次连接请选择一种鉴权方式。OAuth 方式使用 auth_type=oauth2 和 Bearer Token;API Key 方式使用 auth_type=appkey 和签名材料。不要在同一条鉴权帧中同时传两套凭证。

鉴权成功后是否还需要在订阅请求里传 Token?

不需要。鉴权成功后,后续订阅请求使用已建立的连接会话上下文。订阅请求只需要表达订阅动作、标的和数据类型,不要重复传入 Token、AppKey 或内部会话字段。

鉴权成功后为什么订阅仍然失败?

常见原因包括:标的代码无效、账号没有对应市场或品类权限、当前行情权限档不支持该数据类型、订阅配额不足,或请求中的 K 线周期 / 复权方式不合法。请结合 订阅与反订阅错误码频率与配额 排查。

下一步