danmaku: WS join 强制 live-token 校验并锁定昵称(服务端校验 user,忽略客户端声明)
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user