danmaku: WS join 强制 live-token 校验并锁定昵称(服务端校验 user,忽略客户端声明)

This commit is contained in:
RRRosmontis
2026-09-06 00:49:03 +08:00
parent 2fffaada8f
commit cb14347956
2 changed files with 43 additions and 2 deletions
+42 -2
View File
@@ -17,6 +17,34 @@ logging.basicConfig(
]
)
logger = logging.getLogger("danmaku")
MSG_NO_LOGIN = "未登录,无法加入弹幕"
MSG_BAD_TOKEN = "登录已失效,请刷新页面重试"
NICK_GUEST = "观众"
# ==================== 弹幕登录校验(live token -> live-api) ====================
import os as _os
VERIFY_URL = 'https://api.rrrosmontis.icu/v1/live/api/auth/verify'
try:
_cfg = json.load(open(_os.path.join(_os.path.dirname(_os.path.abspath(__file__)), 'danmaku_auth.json'), encoding='utf-8'))
VERIFY_URL = _cfg.get('verify_url', VERIFY_URL)
except Exception:
pass
def _verify_token_sync(token):
try:
import urllib.request as _ur
req = _ur.Request(VERIFY_URL, data=json.dumps({'token': token}).encode('utf-8'), headers={'Content-Type': 'application/json'})
with _ur.urlopen(req, timeout=6) as resp:
d = json.loads(resp.read().decode('utf-8'))
return d.get('user') if d.get('ok') else None
except Exception:
return None
async def _verify_token(token):
return await asyncio.to_thread(_verify_token_sync, token)
# ==================== 直播间类 ====================
class LiveRoom:
@@ -56,6 +84,7 @@ app = FastAPI()
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
client_host = websocket.client.host if websocket.client else "unknown"
token = (websocket.query_params.get('token') or '').strip()
logger.info(f"新WebSocket连接: {client_host}")
current_room: LiveRoom = None
@@ -82,8 +111,19 @@ async def websocket_endpoint(websocket: WebSocket):
current_room.connections.discard(websocket)
# 加入新房间
# 登录校验: 弹幕连接必须携带有效 live token (?token=)
if not token:
await websocket.send_json({"type": "error", "message": MSG_NO_LOGIN})
await websocket.close(code=4401)
return
user_info = await _verify_token(token)
if not user_info:
await websocket.send_json({"type": "error", "message": MSG_BAD_TOKEN})
await websocket.close(code=4401)
return
current_room = await get_or_create_room(room_id)
current_user = data.get("user", "匿名")
current_user = user_info.get("nickname") or NICK_GUEST
async with current_room.connections_lock:
current_room.connections.add(websocket)
@@ -106,7 +146,7 @@ async def websocket_endpoint(websocket: WebSocket):
continue
text = data.get("text", "")
user = data.get("user", current_user or "匿名")
user = current_user or NICK_GUEST
danmaku = {
"text": text,
"user": user,