- 首页/播放页: 去掉 antd Layout 改用 div 避免 flex 布局问题
- 播放页: 返回按钮改为 navigate('/') 替代 window.close()
- 后端登录/验证: 改用 POST JSON body 替代 query param
- 后端鉴权: require_auth 依赖注入保护所有管理接口
- nodes路由: 修复 /strategy 被 /{node_id} 拦截的顺序问题
- 前端 Settings: 策略更新改为 JSON body
49 lines
1.3 KiB
Python
49 lines
1.3 KiB
Python
import hashlib
|
|
from fastapi import APIRouter, HTTPException, Depends, Header
|
|
from pydantic import BaseModel
|
|
from config import settings
|
|
|
|
router = APIRouter(prefix="/api/auth", tags=["auth"])
|
|
|
|
_tokens: set[str] = set()
|
|
|
|
|
|
class LoginRequest(BaseModel):
|
|
password: str
|
|
|
|
|
|
class VerifyRequest(BaseModel):
|
|
token: str
|
|
|
|
|
|
def hash_password(pw: str) -> str:
|
|
return hashlib.sha256(f"{pw}:livestream-salt".encode()).hexdigest()
|
|
|
|
|
|
ADMIN_HASH = hash_password(settings.admin_password)
|
|
|
|
|
|
async def require_auth(authorization: str = Header(None)) -> bool:
|
|
if not authorization:
|
|
raise HTTPException(status_code=401, detail="Missing token")
|
|
token = authorization.replace("Bearer ", "")
|
|
if token not in _tokens:
|
|
raise HTTPException(status_code=401, detail="Invalid token")
|
|
return True
|
|
|
|
|
|
@router.post("/login")
|
|
async def login(body: LoginRequest):
|
|
if hash_password(body.password) != ADMIN_HASH:
|
|
raise HTTPException(status_code=401, detail="Invalid password")
|
|
token = hashlib.sha256(f"{body.password}:token".encode()).hexdigest()
|
|
_tokens.add(token)
|
|
return {"token": token}
|
|
|
|
|
|
@router.post("/verify")
|
|
async def verify(body: VerifyRequest):
|
|
if body.token not in _tokens:
|
|
raise HTTPException(status_code=401, detail="Invalid token")
|
|
return {"valid": True}
|