diff --git a/main/xiaozhi-server/core/connection.py b/main/xiaozhi-server/core/connection.py index 4152e926..bd14a6fd 100644 --- a/main/xiaozhi-server/core/connection.py +++ b/main/xiaozhi-server/core/connection.py @@ -11,7 +11,6 @@ import traceback import subprocess import websockets -from core.ota_auth import AuthManager from core.utils.util import ( extract_json_from_string, check_vad_update, @@ -69,17 +68,6 @@ class ConnectionHandler: self.logger = setup_logging() self.server = server # 保存server实例的引用 - # 认证相关 - auth_config = self.config["server"].get("auth", {}) - self.auth_enable = auth_config.get("enabled", False) - # 设备白名单 - self.allowed_devices = set( - auth_config.get("allowed_devices", []) - ) - secret_key = auth_config.get("signature_key", "") - expire_seconds = auth_config.get("expire_seconds", None) - self.auth = AuthManager(secret_key=secret_key, expire_seconds=expire_seconds) - self.need_bind = False self.bind_code = None self.read_config_from_api = self.config.get("read_config_from_api", False) @@ -208,23 +196,6 @@ class ConnectionHandler: self.device_id = self.headers.get("device-id", None) - # 是否开启了认证,如果开启了则进行认证,否则不认证 - if self.auth_enable: - # 如果启用了白名单则优先处理白名单 - if self.allowed_devices and self.device_id not in self.allowed_devices: - raise AuthenticationError("未经授权的DeviceID") - else: - # 否则校验token - token = self.headers.get("authorization", "") - if token.startswith('Bearer '): - token = token[7:] # 移除'Bearer '前缀 - else: - raise AuthenticationError("Missing or invalid Authorization header") - # 进行认证 - auth_success = self.auth.verify_token(token, client_id=self.headers.get("client-id"), username=self.headers.get("device-id")) - if not auth_success: - raise AuthenticationError("Invalid token") - # 认证通过,继续处理 self.websocket = ws diff --git a/main/xiaozhi-server/core/websocket_server.py b/main/xiaozhi-server/core/websocket_server.py index 09ba7961..b3a5a7d9 100644 --- a/main/xiaozhi-server/core/websocket_server.py +++ b/main/xiaozhi-server/core/websocket_server.py @@ -1,8 +1,12 @@ import asyncio +import json + import websockets from config.logger import setup_logging +from core.auth import AuthenticationError from core.connection import ConnectionHandler from config.config_loader import get_config_from_api +from core.ota_auth import AuthManager from core.utils.modules_initialize import initialize_modules from core.utils.util import check_vad_update, check_asr_update @@ -32,6 +36,16 @@ class WebSocketServer: self.active_connections = set() + auth_config = self.config["server"].get("auth", {}) + self.auth_enable = auth_config.get("enabled", False) + # 设备白名单 + self.allowed_devices = set( + auth_config.get("allowed_devices", []) + ) + secret_key = auth_config.get("signature_key", "") + expire_seconds = auth_config.get("expire_seconds", None) + self.auth = AuthManager(secret_key=secret_key, expire_seconds=expire_seconds) + async def start(self): server_config = self.config["server"] host = server_config.get("ip", "0.0.0.0") @@ -44,6 +58,18 @@ class WebSocketServer: async def _handle_connection(self, websocket): """处理新连接,每次创建独立的ConnectionHandler""" + # 先认证,后建立连接 + try: + await self._handle_auth(websocket) + except AuthenticationError: + await websocket.send(json.dumps({ + "type": "alert", + "status": "ERROR", + "message": "认证失败", + "emotion": "sad" + })) + await websocket.close() + return # 创建ConnectionHandler时传入当前server实例 handler = ConnectionHandler( self.config, @@ -136,3 +162,24 @@ class WebSocketServer: except Exception as e: self.logger.bind(tag=TAG).error(f"更新服务器配置失败: {str(e)}") return False + + async def _handle_auth(self, websocket): + # 先认证,后建立连接 + if self.auth_enable: + headers = dict(websocket.request.headers) + device_id = headers.get("device-id", None) + client_id = headers.get("client-id", None) + # 如果启用了白名单则优先处理白名单 + if self.allowed_devices and device_id not in self.allowed_devices: + raise AuthenticationError("未经授权的DeviceID") + else: + # 否则校验token + token = headers.get("authorization", "") + if token.startswith('Bearer '): + token = token[7:] # 移除'Bearer '前缀 + else: + raise AuthenticationError("Missing or invalid Authorization header") + # 进行认证 + auth_success = self.auth.verify_token(token, client_id=client_id, username=device_id) + if not auth_success: + raise AuthenticationError("Invalid token")