Go to file
xuhongyuan 15a7546a59 feat(auth): 基于 casbin 的登录与 RBAC 权限系统
- 引入 github.com/casbin/casbin/v2 实现 RBAC (model.conf + policy.csv)
- 角色: admin/publisher/viewer/guest,资源: config/room/user/srs,动作: read/list/publish/subscribe/stop/watch/manage
- JWT 登录 (golang-jwt/jwt/v5,bcrypt 存储,data/users.json 持久化,种子用户 admin/publisher/viewer)
- 中间件: HTTP AuthorizeMiddleware + gRPC Unary/Stream 拦截器,支持 Authorization Bearer/Cookie/Query/X-Token
- 新增 API: POST /api/auth/login|register|logout, GET /api/auth/me|users|check, POST /api/auth/users/role (Casbin 鉴权)
- 保护业务路由: /api/publish/subscribe/stop/rooms/room/*/events/srs/streams 及媒体代理 /rtc/v1/* /api/cf/*
- gRPC 契约新增 Login/Register/GetMe/ListUsers/UpdateUserRole (api/live_sfu.proto + gen)
- 前端 login.html + app.js 自动附加 Authorization,SSE 通过 ?token 传递,未登录自动跳转
- 配置: JWT_SECRET/JWT_TTL/CASBIN_MODEL/CASBIN_POLICY/AUTH_USER_FILE/ALLOW_REGISTER
- 集成 TursoDB 持久化与测试覆盖 (auth_test.go)
2026-08-19 16:42:17 +08:00
api feat(auth): 基于 casbin 的登录与 RBAC 权限系统 2026-08-19 16:42:17 +08:00
cmd/server feat(auth): 基于 casbin 的登录与 RBAC 权限系统 2026-08-19 16:42:17 +08:00
data feat(auth): 基于 casbin 的登录与 RBAC 权限系统 2026-08-19 16:42:17 +08:00
deploy feat(auth): 基于 casbin 的登录与 RBAC 权限系统 2026-08-19 16:42:17 +08:00
docs feat(auth): 基于 casbin 的登录与 RBAC 权限系统 2026-08-19 16:42:17 +08:00
gen feat(auth): 基于 casbin 的登录与 RBAC 权限系统 2026-08-19 16:42:17 +08:00
internal feat(auth): 基于 casbin 的登录与 RBAC 权限系统 2026-08-19 16:42:17 +08:00
.env.example feat(auth): 基于 casbin 的登录与 RBAC 权限系统 2026-08-19 16:42:17 +08:00
.gitignore feat(auth): 基于 casbin 的登录与 RBAC 权限系统 2026-08-19 16:42:17 +08:00
README.md feat(auth): 基于 casbin 的登录与 RBAC 权限系统 2026-08-19 16:42:17 +08:00
buf.gen.yaml feat: live SFU fan-out demo (Cloudflare Realtime + SRS) 2026-08-17 15:14:51 +08:00
go.mod feat(auth): 基于 casbin 的登录与 RBAC 权限系统 2026-08-19 16:42:17 +08:00
go.sum feat(auth): 基于 casbin 的登录与 RBAC 权限系统 2026-08-19 16:42:17 +08:00

README.md

直播 SFU 分流 Demo(Cloudflare Realtime · SRS)

参考 GOSpeak 技术栈的直播 SFU 分流演示。控制面用 protobuf / gRPC 定义,媒体面走 Cloudflare Realtime(主 SFU)与 SRS(本地对照)的 WebRTC 扇出。

  • 一路推流 → SFU 扇出 → 多路拉流。
  • 同一路发布可同时落到 Cloudflare Realtime 与 SRS 两条分发链路(分流)。
  • 浏览器经服务端反向代理直连 SFU,凭证不出服务端。
  • 默认 DB 使用 Turso 嵌入式 (libSQL file):房间分发拓扑持久化到本地文件。

目录结构

app/live-sfu-demo/
  api/live_sfu.proto      # protobuf 控制面契约
  gen/                    # buf generate 产出(Go)
  internal/
    config/               # 运行参数(对齐 GOSpeak 的 env 布局)
    db/                   # Turso 嵌入式 (libSQL file) 持久化
    sfu/cloudflare/       # Cloudflare Realtime REST 客户端 + Provider
    sfu/srs/              # SRS Provider
    server/               # gRPC 服务 + JSON 网关 + SRS/CF 媒体反代 + 房间扇出状态
      static/             # 浏览器 UI(发布 / 观看 / 分发面板)
  cmd/server/main.go
  deploy/                 # docker-compose.yml + srs.conf

运行(SRS 链路,开箱即跑)

# 1) 起本地 SRS(WHIP/WHEP/HLS 三协议后端,见 docs/streaming-pipeline.md)
cd app/live-sfu-demo/deploy && SRS_CANDIDATE=127.0.0.1 docker compose up -d srs

# 2) 起 Demo 控制面(默认 Turso 嵌入式,无需额外配置)
cd app/live-sfu-demo
cp .env.example .env
go run ./cmd/server

# 3) 打开浏览器
#    发布: http://localhost:8088/publish?room=demo
#    观看: http://localhost:8088/watch?room=demo

两个标签页用同一房间名即可配对。发布页勾选的分发后端会在「分发状态」中实时显示。

默认 DB:Turso 嵌入式

房间的“分发目标”拓扑(stream_targets)默认持久化到 Turso 嵌入式(github.com/tursodatabase/go-libsql 的 SQLite 兼容 file 模式),而非纯内存。

  • DSN:TURSO_DATABASE_URL=file:./data/live-sfu.db?cache=shared&_journal_mode=WAL(默认)
    • 兼容 DATABASE_URL 覆盖
    • 仅支持嵌入 file: / :memory:,拒绝 libsql:// 远程(嵌入适配专注单机持久化)
    • 自动建表 (stream_targets, rooms),SetMaxOpenConns(1) 适配 SQLite 单写模型
    • 重启后自动 LoadAll 恢复房间
# 默认即嵌入文件
TURSO_DATABASE_URL=file:./data/live-sfu.db?cache=shared&_journal_mode=WAL

# 内存(测试)
TURSO_DATABASE_URL=file::memory:?cache=shared

# 验证持久化:发布后重启,/api/rooms 仍在
curl http://localhost:8088/api/rooms | jq
sqlite3 data/live-sfu.db "select room, backend, stream from stream_targets;"

运行(Cloudflare Realtime 链路,主 SFU)

在 .env 填入 Cloudflare Realtime 凭证后,go run ./cmd/server 即启用主 SFU:

CF_APP_ID=xxxxxxxxxxxx
CF_APP_SECRET=xxxxxxxxxxxx
  • 发布:服务端用 CF_APP_SECRET 创建 Cloudflare session,浏览器只交换 SDP(/api/cf/... 反代注入 Bearer)。
  • 观看:服务端为观众创建 viewer session,并订阅发布者 session 的轨道(location=remote)。

Cloudflare 未配置时,UI 会标注「未配置」,SRS 链路不受影响。

protobuf / gRPC

# 修改 api/live_sfu.proto 后重新生成
export PATH="$HOME/go/bin:$PATH"
buf generate api

契约(LiveSFU 服务):GetConfig / ListRooms / Publish / Subscribe / StopStream / WatchRoom(服务端流式推送房间分发拓扑)。gRPC 监听 GRPC_PORT(默认 9090),浏览器走同端口 的 JSON 网关(protojson)。

文档

分流拓扑

 publisher ──WHIP/tracks.new──▶ Cloudflare Realtime SFU ──▶ viewer(s)
          └────WHIP────────────▶ SRS SFU ─┬─▶ WHEP  viewer(s)  (低延时 0.2-0.5s)
                                         ├─▶ HLS   viewer(s)  (PC→WHIP→SRS→HLS 延时 5-10s,全端兼容)
                                         └─▶ FLV   viewer(s)
                一路 WHIP 推流,SRS 自动 remux 三协议同出;房间分发目标由 WatchRoom 实时广播,观众任选后端拉流

详见 docs/streaming-pipeline.md — 默认已开启 HLS,Go 网关反代 /live/*.m3u8,前端 iOS 原生 / hls.js 双兼容。