跳转到内容

流鉴权

Monibuca v6 支持三种互补的流鉴权 / 准入能力:

  1. 内置签名鉴权(secret + expire,MD5)
  2. 自定义鉴权处理器(在 enable_auth 开启时优先于 MD5)
  3. Signed Policy(HMAC-SHA256 URL/query 门禁,独立于 enable_auth

另有同步 admission webhook(HTTP 准入),在 verify_stream_auth 之后由协议钩子调用,语义不变。

每个推流/拉流请求按以下顺序过闸,任一环节失败即拒绝:

  1. MD5 / 自定义处理器(仅当 enable_auth: true 且配置了 key)
  2. Signed Policy(当 signed_policy 启用且 action/protocol 匹配)
  3. Admission webhook(当 admission_webhook 启用且 action/protocol 匹配;可改写 stream_path

三者相互独立、可任意组合;全部关闭时保持零开销的默认行为。

协议(protocol 取值)推流(publish)拉流(play)说明
rtmp拒绝时直接断开连接
webrtc✅ WHIP✅ WHEP拒绝时返回 HTTP 401
srt握手阶段以 Unauthorized 拒绝
rtsp✅ record/announce✅ describe/playRTSP 401
webtransport会话关闭
hls仅 playlist/master 走准入;.ts/分片只做鉴权
flvHTTP-FLV 与 WS-FLV
mp4HTTP MP4 拉流

表中 protocol 取值同时用于 Signed Policy 的 protocols 过滤、admission webhook 的 protocols 过滤及请求体中的 protocol 字段。

global:
enableauth: true
publish:
key: "your-publish-key"
secretargname: secret
expireargname: expire
subscribe:
key: "your-subscribe-key"

说明:

  • enableauth=true 时开启鉴权逻辑
  • 推流使用 publish.key
  • 拉流使用 subscribe.key
  • 参数名可通过 secretargname / expireargname 覆盖,默认分别是 secret / expire

签名计算:

secret = md5(key + streamPath + expireHex)

其中:

  • keypublish.keysubscribe.key
  • streamPath:不含 query 的流路径(如 live/test
  • expireHex:16 进制 Unix 时间戳(秒)

校验规则:

  • expire 必须可解析为 16 进制时间戳,且未过期
  • secret 长度必须为 32
  • secret 与服务端计算值(忽略大小写)一致

live/test 为例:

rtmp://host/live/test?secret=...&expire=...
http://host:8180/flv/live/test.flv?secret=...&expire=...
http://host:8180/hls/live/test/index.m3u8?secret=...&expire=...
http://host:8180/webrtc/push/live/test?secret=...&expire=...
http://host:8180/webrtc/play/live/test?secret=...&expire=...
srt://host:6000?streamid=publish:/live/test?secret=...&expire=...

除本地 secret+expire / 自定义处理器外,可配置同步 HTTP 准入 Webhook(OME AdmissionWebhooks 风格),在创建推流/拉流会话前向控制面询问 allow/deny,并支持改写 stream_path

覆盖协议见上文协议覆盖表。

global:
admission_webhook:
enable: false
url: "https://ctrl.example/v1/admission"
secret: "shared-secret" # 可选;设置后发送 X-Monibuca-Signature: sha256=<hex>
timeout_ms: 3000 # 单次请求硬超时(毫秒),不重试
fail_policy: closed # closed | open(仅 opening 生效)
notify_closing: false # 会话结束时 best-effort POST status=closing
actions: [publish, play] # 省略 = 两者
protocols: [webrtc, rtmp] # 省略 = 全部已接入协议

路径改写由 admission 在 Signed Policy 校验之后发生;MVP 下 policy 绑定的是客户端请求的原始 stream_path

Monibuca 向 url 发送 POST JSON,请求头包含 X-Monibuca-Event: admission.openingX-Monibuca-Delivery(幂等 ID),以及可选的 X-Monibuca-Signature: sha256=<hex>(对请求体做 HMAC-SHA256):

{
"action": "publish",
"protocol": "rtmp",
"status": "opening",
"stream_path": "live/cam01",
"url": "rtmp://host/live/cam01?token=abc",
"client": { "ip": "203.0.113.7", "port": 51234, "user_agent": "OBS" },
"query": { "token": "abc" },
"session_id": null,
"time": "2026-07-17T12:00:00Z"
}

控制面返回 2xx + JSON:

{
"allowed": true,
"stream_path": "live/real-cam01",
"reason": "ok"
}
字段必填说明
allowed缺失或 false 均视为拒绝
stream_path改写后的流路径(仅路径,不含 host/协议)
lifetime_ms已记录但 MVP 未强制执行(HLS/FLV/MP4 分片 GET 不受控)
reason建议仅在控制面侧记录;客户端只收到 401 等通用错误

closed(默认)在超时/网络错误/非 2xx/无效 JSON 时拒绝open 在同样故障时放行并输出 warn 日志(仅建议开发环境)。

enablenotify_closing: true 时,会话型协议在会话正常结束时会向控制面 fire-and-forget POST(status: "closing",头 X-Monibuca-Event: admission.closing)。响应体忽略;失败只打 warn不阻塞 teardown,也不套用 fail_policy

会发 closing不发 closing
WebRTC WHIP/WHEP、RTMP、SRTHLS / HTTP-FLV / MP4(无持久会话)
RTSP / WebTransport(本切片暂未接线)
  • HLS 仅在请求 playlist/master 时走准入;.ts / fMP4 分片 GET 只做鉴权,不逐个回源准入。
  • enable: false 或未配置时为零开销,不改变现有默认行为。

OME SignedPolicy 风格的本地确定性鉴权:对 protocol + action + stream_path + expire 做 HMAC-SHA256,token 放在 query 中。与 enable_auth、admission webhook 互补,默认关闭。

global:
signed_policy:
enable: false
secret: "your-hmac-secret"
token_query: "policy" # token 参数名
expire_query: "expire" # 过期时间参数名(十进制 Unix 秒)
algorithm: "hmac-sha256" # MVP 仅支持此项
actions: ["publish", "play"]
protocols: [] # 空 = 全部协议;如 ["rtmp", "webrtc"]

说明:

  • enable=falsesecret 为空:零开销 no-op
  • actions / protocols 未匹配时跳过(不要求 token)
  • Signed Policy 的 expire十进制 Unix 秒;MD5 鉴权的 expire十六进制。若两者同时开启且共用参数名,请将其一的 expire_query / expireargname 改成不同名字
canonical = "v1\n" + protocol + "\n" + action + "\n" + stream_path + "\n" + expire
policy = hex(HMAC-SHA256(secret, canonical))

其中:

  • protocol:插件名(如 rtmpwebrtchlsflvsrt
  • actionpublishplay
  • stream_path:不含 query 的流路径(如 live/test
  • expire:十进制 Unix 时间戳(秒)
import hmac, hashlib, time
secret = b"your-hmac-secret"
protocol = "rtmp"
action = "play"
stream_path = "live/test"
expire = str(int(time.time()) + 3600)
canonical = f"v1\n{protocol}\n{action}\n{stream_path}\n{expire}"
policy = hmac.new(secret, canonical.encode(), hashlib.sha256).hexdigest()
print(f"?policy={policy}&expire={expire}")
Terminal window
SECRET="your-hmac-secret"
PROTOCOL="rtmp"
ACTION="play"
STREAM_PATH="live/test"
EXPIRE=$(( $(date +%s) + 3600 ))
POLICY=$(printf 'v1\n%s\n%s\n%s\n%s' "$PROTOCOL" "$ACTION" "$STREAM_PATH" "$EXPIRE" \
| openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')
echo "?policy=${POLICY}&expire=${EXPIRE}"
rtmp://host/live/test?policy=...&expire=1735689600
http://host:8180/hls/live/test/index.m3u8?policy=...&expire=1735689600

失败时返回与现有鉴权相同的 auth error(缺失 / 过期 / 签名错误均拒绝)。

当你希望接入外部用户系统、权限中心或一次性票据时,可注册自定义鉴权处理器。

行为优先级(在 enable_auth 路径内):

  1. 自定义处理器(如果已注册)
  2. 内置 secret+expire 鉴权

自定义处理器返回后,若开启了 Signed Policy 且匹配 action/protocol,仍须通过 Signed Policy。

StreamManagerApi 提供:

  • set_stream_auth_handler(handler)

处理器签名:

  • 输入:StreamAuthRequest
    • plugin_name
    • stream_path
    • query_string
    • params(已解析 query map)
    • is_publish
  • 返回:Result<()>
    • Ok(()):鉴权通过
    • Err(...):鉴权失败
manager.set_stream_auth_handler(Some(Arc::new(|req| {
if req.plugin_name == "rtmp" && req.is_publish {
let token = req.params.get("token").cloned().unwrap_or_default();
if token == "allow" {
return Ok(());
}
return Err(sdk::MonibucaError::InvalidInput("auth failed".into()));
}
Ok(())
})));

signed_policyadmission_webhook 均已注册到全局配置页/config 下的全局配置表单,即 Admin 的配置入口),分别位于「Signed Policy 门禁」与「准入 Webhook」分组,字段与上文 YAML 一一对应(密钥字段以密码框展示)。

注意:

  • 通过配置页保存需要启用数据库(DB 配置持久化);未启用数据库时请直接编辑 config.yaml
  • 两个功能的开关都要求配套字段非空才生效(Signed Policy 需 secret,admission 需 url),只勾选 enable 不会产生效果。

Admin 的「推流地址」弹窗支持按相同规则自动生成:

  • expire(16 进制时间戳)
  • secretmd5(key + streamPath + expire)

生成后会自动拼接到地址 query 中。

服务端提供签名生成接口:

GET /v6/api/streams/secret?stream_path={streamPath}&type={publish|subscribe}&expire=<hex>&plugin=<pluginName>

参数说明:

  • stream_path:流路径
  • typepublishsubscribe,默认 publish
  • expire:可选,16 进制 Unix 时间戳;不传默认当前时间 + 30 分钟
  • plugin:可选,插件名(默认 global,即使用全局继承 key)

返回示例:

{
"secret_type": "publish",
"plugin": "rtmp",
"stream_path": "live/test",
"expire": "6610f4a0",
"secret": "0123456789abcdef0123456789abcdef"
}

联系我们

微信公众号:不卡科技 微信公众号二维码
腾讯频道:流媒体技术 腾讯频道二维码
QQ 频道:p0qq0crz08 QQ 频道二维码
QQ 群:751639168 QQ 群二维码