From 5e06c17b52a853a828644fdabbcfe382a52dd069 Mon Sep 17 00:00:00 2001 From: qinglong Date: Sat, 13 Jun 2026 17:45:58 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20WebSocket=20=E9=89=B4=E6=9D=83=20?= =?UTF-8?q?=E2=80=94=20Cookie=20=E4=BC=98=E5=85=88=20(=E6=94=AF=E6=8C=81?= =?UTF-8?q?=20HttpOnly)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因: panel_token 是 HttpOnly cookie, JS getCookie() 读不到 → 前端 WS ?token= 参数为空 → 认证失败 → 仪表盘无数据 修复: - _ws_auth_wrapper: Cookie 优先 → query token 备用 → API Key - 浏览器同源 WS 自动发送 Cookie, 无需 ?token= - dashboard.js / logs.js 移除多余的 getCookie+?token= Co-Authored-By: Claude --- config/framework/base_config.yaml.bak | 56 ++++++++++++++++++++++++ config/permissions/pending_requests.json | 11 +++++ config/plugins/commands.yaml | 2 +- config/services/network_routes.yaml | 2 +- services/web_panel/routes/status.py | 16 +++++-- static/web_panel/pages/dashboard.js | 3 +- static/web_panel/pages/logs.js | 3 +- 7 files changed, 84 insertions(+), 9 deletions(-) create mode 100644 config/framework/base_config.yaml.bak diff --git a/config/framework/base_config.yaml.bak b/config/framework/base_config.yaml.bak new file mode 100644 index 0000000..2ac0282 --- /dev/null +++ b/config/framework/base_config.yaml.bak @@ -0,0 +1,56 @@ +framework: + debug: true + name: SenSu + version: v0.6.0 +logging: + debug_level_file: true + level: DEBUG + max_file_size: 10MB + max_log_files: 20 +plugins: + auto_load: true + hot_reload: true + max_retry_count: 3 + isolation: true +# 自动启动脚本 — 框架启动时后台拉起 +auto_start_scripts: + enabled: true + scripts: [] + # 示例: + # - name: cyrene_debug + # path: ~/cyrene_debug_server.py + # enabled: true + # args: [] + # cwd: ~ +# TUI配置 +tui: + enabled: true + refresh_rate: 30 + # TUI布局配置 + layout: + grid_rows: "4fr 5fr 1fr" # 三行布局:日志区域、消息区域、输入区域的比例 + # TUI样式配置 + styles: + log_area: "border: solid green; overflow-y: auto;" + message_area: "border: solid yellow; overflow-y: auto;" + input_area: "border: solid red;" + # TUI日志显示配置 + log_display: + max_lines: 200 +# 互联网服务配置 +internet: + websocket: + host: "0.0.0.0" + port: 4240 + # 其他websocket配置... + http: + host: "0.0.0.0" + port: 4200 + # 其他http配置... +panel: + entrance: + path: "/SenSu" + username: "admin" + password: "admin" + + \ No newline at end of file diff --git a/config/permissions/pending_requests.json b/config/permissions/pending_requests.json index edccd72..c7beff1 100644 --- a/config/permissions/pending_requests.json +++ b/config/permissions/pending_requests.json @@ -42,5 +42,16 @@ "framework.command.execute" ], "timestamp": 17177.106703342 + }, + "fe262a42": { + "plugin_name": "sentinel", + "permissions": [ + "plugin.sentinel.read", + "plugin.sentinel.write", + "plugin.network.access", + "framework.event.subscribe", + "framework.command.execute" + ], + "timestamp": 25770.11842246 } } \ No newline at end of file diff --git a/config/plugins/commands.yaml b/config/plugins/commands.yaml index 76aca92..f2db31f 100644 --- a/config/plugins/commands.yaml +++ b/config/plugins/commands.yaml @@ -93,7 +93,7 @@ commands: permissions: - framework.command.test source: internal -last_updated: 17177.060053342 +last_updated: 25770.099665272 plugin_commands: sentinel: sentinel: *id001 diff --git a/config/services/network_routes.yaml b/config/services/network_routes.yaml index fe6c6e1..dfc655b 100644 --- a/config/services/network_routes.yaml +++ b/config/services/network_routes.yaml @@ -1,5 +1,5 @@ http_port: 4200 -last_updated: 17177.1104973 +last_updated: 25770.118859595 plugin_routes: sentinel: - methods: diff --git a/services/web_panel/routes/status.py b/services/web_panel/routes/status.py index 7ab8a64..12bfc3d 100644 --- a/services/web_panel/routes/status.py +++ b/services/web_panel/routes/status.py @@ -13,11 +13,21 @@ logger = logging.getLogger(__name__) _sys_ws_clients: set = set() def _ws_auth_wrapper(handler): - """WebSocket 鉴权包装 — 从 query string 取 token 验证""" + """WebSocket 鉴权 — Cookie 优先(同源自动发送), query token 备用""" async def wrapper(request): - token = request.query.get("token", "") + # 1. Cookie (浏览器同源自动发送, 支持 HttpOnly) + token = request.cookies.get("panel_token", "") + # 2. Query string token 备用 (跨域/非浏览器客户端) + if not token: + token = request.query.get("token", "") + # 3. API Key 验证 session_store = request.app.get("panel_session_store", {}) - if not token or token not in session_store: + is_valid = token and token in session_store + if not is_valid and token: + from services.web_panel.routes.apikeys import validate_api_key + is_valid = validate_api_key(token) is not None + + if not is_valid: ws = web.WebSocketResponse() await ws.prepare(request) await ws.send_str(json.dumps({"error": "Unauthorized"})) diff --git a/static/web_panel/pages/dashboard.js b/static/web_panel/pages/dashboard.js index 980c521..27bcfb7 100644 --- a/static/web_panel/pages/dashboard.js +++ b/static/web_panel/pages/dashboard.js @@ -32,8 +32,7 @@ window.DashboardModule = { } var base = window.location.pathname.split("/").slice(0, 2).join("/"); - var tok = getCookie("panel_token"); - var ws = new WebSocket("ws://" + location.host + base + "/api/system/ws?token=" + (tok || "")); + var ws = new WebSocket("ws://" + location.host + base + "/api/system/ws"); self.ws = ws; ws.onopen = function() { diff --git a/static/web_panel/pages/logs.js b/static/web_panel/pages/logs.js index 83c3a8e..1ac02bd 100644 --- a/static/web_panel/pages/logs.js +++ b/static/web_panel/pages/logs.js @@ -25,8 +25,7 @@ window.LogsModule = { } var base = window.location.pathname.split("/").slice(0, 2).join("/"); - var tok = getCookie("panel_token"); - var ws = new WebSocket("ws://" + location.host + base + "/api/logs/ws?token=" + (tok || "")); + var ws = new WebSocket("ws://" + location.host + base + "/api/logs/ws"); self.ws = ws; ws.onopen = function() {